我的通用函数之一中的可分配值有问题:
interface BuildArguments<T extends string> {
type: T;
}
type PromiseResult<T> =
T extends 'standalone' ? Promise<void> :
T extends 'all' ? Promise<void> :
Promise<void[]>;
const foo: PromiseResult<'standalone'> = Promise.resolve();
const bar: PromiseResult<'all'> = Promise.resolve();
const baz: PromiseResult<'foo'> = Promise.resolve([]);
bundle({ type: 'foo' });
function bundle<T extends string>(buildArguments: BuildArguments<T>): PromiseResult<T> {
switch (buildArguments.type) {
case 'standalone':
return Promise.resolve(); // error here, not assignable to PromiseResult<T>
case 'all':
return Promise.resolve(); // error here, not assignable to PromiseResult<T>
default:
return Promise.all([ // error here, not assignable to PromiseResult<T>
Promise.resolve(),
Promise.resolve()
]);
}
}
Run Code Online (Sandbox Code Playgroud)
的const小号foo,bar并baz显示该条件类型工作正常。如果您使用 ts playground 并将鼠标悬停在它上面,函数调用bundle({ type: 'foo' })也会正确提供类型Promise<void[]>。为什么它不适用于返回值?我也试过这是因为 TypeScript 无法T通过向kind: T函数添加参数来推断,但没有任何变化。断言Promise.resolve()到PromiseResult<T>工作正常。
只要条件类型仍有未解析的条件类型(如T中的情况PromiseResult<T>),打字稿通常不会让您对条件类型做太多事情
此外,在这种情况下,您假设缩小会buildArguments.type变窄T。它不是。缩小会缩小一个值,而不是整个类型参数。这是不可能的,考虑这个例子:
function foo<T extends string | number>(a: T, b: T) {
if(typeof a === "string") {
// should b be string? No
}
}
foo<string | number>(1, "");
Run Code Online (Sandbox Code Playgroud)
仅仅因为我们缩小了一个类型的值T与其他此类变量无关。
最简单的解决方案是使用更宽松的单独实现签名,同时使用对调用者更好的条件类型保留公共签名:
function bundle<T extends string>(buildArguments: BuildArguments<T>): PromiseResult<T>
function bundle(buildArguments: BuildArguments<string>): PromiseResult<'standalone' | 'all'> | PromiseResult<string> {
switch (buildArguments.type) {
case 'standalone':
return Promise.resolve();
case 'all':
return Promise.resolve();
default:
return Promise.all([
Promise.resolve(),
Promise.resolve()
]);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1097 次 |
| 最近记录: |