我试图了解 TypeScript 条件类型的工作原理。这是我的代码。有类型错误:
interface MyType {
name: string;
}
const testFunc = <T extends MyType | string>(
what: T
): T extends MyType ? MyType : string => {
if (typeof what === 'object') {
return what['name'];
}
return what;
};
Run Code Online (Sandbox Code Playgroud)
正确的用法是什么?
TestFunc您的代码中的函数应该string在每种情况下都返回。我认为这是一种错字。让我们修复它并继续。
后来我想出了一个更安全的解决方案(我把我的旧答案留在了底部)。最好使用重载。在重载中描述条件逻辑,在函数中使用联合类型。
interface MyType {
name: string;
}
function testFunc<T extends MyType | string>(
what: T
): T extends MyType ? string : MyType;
function testFunc(what: MyType | string): MyType | string {
if (typeof what === 'object') {
return what.name;
}
return { name: what };
}
Run Code Online (Sandbox Code Playgroud)
旧答案:
interface MyType {
name: string;
}
type TestFunc = <T extends MyType | string>(what: T) => T extends MyType ? string : MyType;
const testFunc: TestFunc = (what: any) => {
if (typeof what === 'object') {
return what.name;
}
return { name: what };
};
Run Code Online (Sandbox Code Playgroud)
或者,如果您更喜欢定义内联类型:
interface MyType {
name: string;
}
const testFunc: <T extends MyType | string>(what: T) =>
T extends MyType ? string : MyType =
(what: any) => {
if (typeof what === 'object') {
return what.name;
}
return { name: what };
};
Run Code Online (Sandbox Code Playgroud)
Typescript 编译器会像这样处理它:
const a1: MyType = testFunc({ name: 'foo' }); // Type 'string' is not assignable to type 'MyType'.
const a2: MyType = testFunc({ name: 1 }); // Error: Argument of type '{ name: number; }'
// is not assignable to parameter of type 'string | MyType'
const a3: string = testFunc({ name: 'foo' }); // Ok
const a4: string = testFunc('foo'); // Error: Type 'MyType' is not assignable to type 'string'.
const a5: MyType = testFunc('foo'); // Ok
Run Code Online (Sandbox Code Playgroud)
这个答案基本上是用更多的文字和代码解释@jcalz 的评论。
你正确理解了这个概念。不幸的是,您在 TS 中遇到了一个警告,在通过控制流分析缩小可能性时,它并没有平等地对待具体类型和泛型类型。
理想情况下,您建议的用法应该是有效的。但是 TS还不支持它。
现在我们需要解决方法,这就是我通常所做的。
interface MyType {
name: string;
}
const testFunc = <T extends MyType | string>(
_what: T
): T extends MyType ? MyType : string => {
// First thing to do once enter the fn body,
// we manually cast to `any` type
var what = _what as any;
if (typeof what === 'object') {
return what['name'];
}
return what;
};
Run Code Online (Sandbox Code Playgroud)
不完美,我知道。这有点像你实现了一个重载的函数,最终你只能使用any类型。但是既然你已经为你的消费者提供了一个完美的函数接口,那么在后台稍微弄脏一点也没关系。
Yak*_*ain -1
我会这样做:
\n\ninterface MyType {\n name: string;\n}\n\nconst testFunc = <T>(what: T): T extends MyType ? MyType : string => {\n if (typeof what === \'object\') {\n return what[\'name\'];\n } \n return what as any;\n\n};\nRun Code Online (Sandbox Code Playgroud)\n\nas any意思是“TypeScript,don\xe2\x80\x99t 抱怨这种类型”。问题是what条件类型没有选择 的缩小类型,因此该函数无法计算条件并将返回类型缩小为what。
| 归档时间: |
|
| 查看次数: |
1668 次 |
| 最近记录: |