【问题标题】:TypeScript generic contraints with extending and default parameters带有扩展参数和默认参数的 TypeScript 通用约束
【发布时间】:2018-08-23 13:13:45
【问题描述】:

所以我正在尝试编写一个具有泛型的函数,该泛型扩展了某个对象,从而限制了它。接下来我想使用这个泛型和一个参数的定义来生成一个新的“增强”参数。 这一切都很好,但是一旦我想为参数引入默认值,TypeScript 就会抱怨如下消息(playground 中的一些不同变体):

功能:

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

错误:

键入'{ foo:字符串; }' 不可分配给类型 'T & { bar?: 布尔值; }'。 对象字面量只能指定已知属性,但类型 'T & { bar?: boolean; 中不存在 'foo' }'。你的意思是写 'foo'?

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

【问题讨论】:

    标签: typescript generics default-value


    【解决方案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】:

      在定义时输入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 || ''; 添加为函数的第一行代码。只是一些想法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-09-22
        • 1970-01-01
        • 2017-05-19
        • 2023-03-10
        相关资源
        最近更新 更多