我试图了解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;
};
正确用法是什么?
答案 0 :(得分:1)
我会这样:
interface MyType {
name: string;
}
const testFunc = <T>(what: T): T extends MyType ? MyType : string => {
if (typeof what === 'object') {
return what['name'];
}
return what as any;
};
as any
的意思是“ TypeScript,不要抱怨这种类型”。问题在于条件类型不会选择what
的缩小类型,因此该函数无法评估条件并将返回类型缩小到what
。
答案 1 :(得分:1)
此答案基本上是用更多的单词和代码解释@jcalz的comment。
您正确理解了这个概念。不幸的是,您在TS中遇到了警告,在通过控制流分析来缩小可能性时,它不会平等地对待具体类型和通用类型。
理想情况下,您建议的用法应该是有效的。但是TS doesn't support it yet。
目前,我们需要解决方法,这是我通常要做的。
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;
};
不完美,我知道。有点像您实现了一个重载函数,最终您只需要使用any
类型。但是,由于您已经为消费者提供了完善的功能界面,因此可以在后台稍作改动。
答案 2 :(得分:1)
在每种情况下,代码中的函数TestFunc
应该返回string
。我认为这是一种错字。让我们对其进行修复,然后继续使其按自己的意愿去做。这将更接近原始代码:
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 };
};
或者,如果您希望内联定义类型:
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 };
};
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