[英]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.