[英]TypeScript type inference from default parameter of type
給出以下示例:
interface Foo {
name: string;
}
interface Bar extends Foo {
displayName: string;
}
const foo: Foo = { name: "foo" };
const bar: Bar = { name: "bar", displayName: "dn" };
const getName = <T extends Foo>(obj: T = foo): string => {
return obj.name;
};
getName(foo); // Ok
getName(bar); // Ok
obj: T = foo
導致錯誤。 即使T extends Foo
,這也不被接受。 為什么會這樣,有什么解決方法?
例子。
您的getName
函數不需要泛型,並且可以對輸入參數obj
使用Foo
類型注釋,即:
const getName = (obj: Foo = foo): string => {
return obj.name;
};
盡管您將類型Foo
分配給obj
它也適用於getName(bar);
因為Bar extends Foo
。 換句話說:由於 TypeScript 知道Foo
比Bar
更具體,因此getName
函數將接受Bar
類型的任何元素。
您不需要泛型,因為您不想將函數的不同部分相互關聯。 如果您想將輸入參數與輸出參數相關聯,則可以有效使用泛型。
請參閱您的代碼的此TS Playground 。
另請參閱有關您遇到的錯誤的相關問題,即
Type 'Foo' is not assignable to type 'T'.
'Foo' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Foo'.(2322)
問題是foo
不是T
類型,假設您想使用接口Bar
實例化泛型:
const getName = (obj: Bar = foo): string => {
return obj.name;
};
您可以看到foo
不是Bar
(缺少displayName
屬性)並且您不能將其分配給Bar
類型的變量。
您現在有三個選擇:
強制foo
用作泛型T
: <T extends Foo>(obj: T = foo as T): string => ...
。 但這是您能做的最糟糕的選擇(可能導致意外結果/錯誤)。
重載您的函數以匹配您的通用規范。 如果您需要返回(並實際使用)您的通用實例,這很有用:
const getName: {
// when you specify a generic on the function
// you will use this overload
<T extends Foo>(obj: T): T;
// when you omit the generic this will be the overload
// chosen by the compiler (with an optional parameter)
(obj?: Foo): Foo;
}
= (obj: Foo = foo): string => ...;
Foo
: (obj: Foo = foo): string => ...
傳遞。 在您的情況下,這應該是最好的
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.