TypeScript泛型约束与扩展和默认参数

时间:2018-03-14 20:48:31

标签: typescript generics default-value

所以我试图编写一个具有泛型的函数,该函数扩展某个对象从而约束它。接下来,我想将这个泛型与参数的定义一起使用,以生成一个新的"增强的"参数。 这一切都很好但是只要我想在参数中引入一个默认值,TypeScript就会发出如下消息的抱怨(playground中有一些不同的变体):

功能:

const test1 = <T extends { foo?: string }>(options: T & { bar?: boolean } = {foo: 
''}) => {
    console.log(options);
}

错误:

  

输入&#39; {foo:string; }&#39;不能指定类型&#39; T&amp; {bar?:   布尔; }&#39 ;.         对象文字可能只指定已知属性,但是“foo”#39;并不存在类型&#39; T&amp; {bar?:boolean; }&#39 ;.你的意思是写   &#39;富&#39;?

编译器警告我,我可能想使用foo,我实际上是这样做的。是否根本不可能以这种方式使用泛型,或者这是TypeScript中的错误?

3 个答案:

答案 0 :(得分:2)

在定义时间类型T未知,因此编译器会抛出此错误,您无法初始化您不知道的内容。我可以想到几种解决方法,但不确定它们对您的案例有多大用处。

您可以保留T类型,并使用options参数的联合类型,如下所示:

const test1 = <T> (options: T | { bar?: boolean } | { foo?: string } = { foo: '' }) => {
  console.log(options);
};

另一种解决方法是使用类型断言并手动告诉编译器初始化程序属于它需要的类型:

const test2 = <T extends { foo?: string }>(options: T & { bar?: boolean } = { foo: '' } as T & { bar?: boolean }) => {
  console.log(options);
};

但请记住,这些只是解决方法,无论何时必须使用变通方法,都意味着设计存在缺陷。也许您可以再次查看您的逻辑并进行改进,以消除对这些变通方法的需求。或者,您可以跳过参数初始化并添加options.foo = options.foo || '';作为函数中的第一行代码。只是一些想法。

答案 1 :(得分:1)

初始化无效的原因是您无法初始化您不了解的内容。请考虑以下呼叫:

test1<{ foo: string, goo: boolean}>();

泛型参数对函数有效,但它有一个额外的属性goo,这是必需的,但在您的默认值选项中未指定。这就是编译器抱怨作业的原因,你不知道T的最终形状,你只知道它的最低要求,所以你不能建立一个兼容的对象含T

如果您对options没有在泛型类型参数上指定所有必需属性,那么可以使用类型断言

const test1 = <T extends { foo?: string }>(options: T & { bar?: boolean } = <any>{foo: ''}) => {
    console.log(options);
}

答案 2 :(得分:0)

如何声明两个函数,一个具有通用接口,第二个具有实际类型和默认功能?

const test1 = <T>(options: T) => {
    console.log(options);
}

const test1WithDefaults = (options) => {
   test1<{foo: string}>({foo: ''})
}
相关问题