【问题标题】:TypeScript generic type parameters are inferred with functions, but not type?TypeScript 泛型类型参数是用函数推断的,但不是类型?
【发布时间】:2020-07-10 03:35:39
【问题描述】:

考虑一下:

type SpecificKeys<T extends string> = {
  [key in T]: string;
};

const foobar: SpecificKeys<"foo" | "bar"> = {
  foo: "foo",
  bar: "bar",
};

在创建foobar 时,我必须将键的并集指定为泛型类型参数,这是多余的。我想不出任何办法。但是如果我写一个无所事事的函数:

function makeSpecificKeys<T extends string>(thing: SpecificKeys<T>): SpecificKeys<T> {
  return thing;
}

const foobarInferred = makeSpecificKeys({
  foo: "foo",
  bar: "bar",
});

那么 const foobarInferred 被正确输入为 SpecificKeys&lt;"foo" | "bar"&gt; 并且我不必通过枚举所有键来重复自己。

有没有什么方法可以在创建类型化变量时实现泛型类型参数的推断,而不必做一个无所事事的函数?

【问题讨论】:

    标签: typescript typescript-generics


    【解决方案1】:

    答案是否定的。类型限制了值,说a:T 表示值a 需要是T 类型的成员,如果不是 - 则编译错误。你想说的是a: infer me typeof a,所以反过来。

    类型注解是用来限制值的,不是值来限制类型的。 TS 允许从值中获取类型,但不允许同时获取值的类型并对其进行限制。


    不过,我们可以制作一些技巧来使其正常工作。考虑类型级解决方案:

    type SpecificKeys<T extends string> = {
      [key in T]: string;
    };
    
    // type level version of makeSpecificKeys
    type MakeSpecificKeys<T extends SpecificKeys<string>> = T;
    
    const foobar = {
      foo: "foo",
      bar: "bar",
    };
    type FoobarType = MakeSpecificKeys<typeof foobar> // fine ?
    
    const badfoobar = {
      foo: 1, // number value dont match SpecificKeys
      bar: "bar",
    };
    type BadFoobarType = MakeSpecificKeys<typeof badfoobar> // error ?
    

    The Playground

    foobarbadfoobar 两个值都由 TS 正确推断,无需任何类型注释。接下来是调用类型级别MakeSpecificKeys,这是您之前创建的一种id 函数,但这是在类型级别,它以与makeSpecificKeys 相同的方式限制参数类型。对于badfoobar,它显示编译错误。

    我在这里展示的无疑是最糟糕的方法,然后是你所做的值构造函数makeSpecificKeys。所以坚持下去。使用上述方法的唯一一点是,当makeSpecificKeys 这样做时,它不会进入运行时。

    【讨论】:

    • 我玩过这种结构。用例是我为第三方消费者提供了一种类型,用于构造有效的 JS 对象作为系统的输入。他们也将消费的其他类型来自它。向他们提供指导以首先创建无类型对象然后使用typeof foobar“查看它们是否工作”似乎有些倒退。我也不希望他们必须使用需要复制所有键作为 typedef 一部分的类型。对于这种情况,就引导用户而言,也许仅仅提供透传功能是最简单的解决方案
    • 真的,我只是希望能够为可能不太高级的 TS 程序员提供关于如何使用我的类型的最简单的指导,所以它主要是关于什么是最好看的例子。但似乎这些都是所有选项,感谢您澄清什么是可能的。
    猜你喜欢
    • 2016-12-05
    • 2016-11-01
    • 1970-01-01
    • 2020-01-23
    • 1970-01-01
    • 2020-03-11
    • 2020-09-09
    • 2019-09-17
    • 1970-01-01
    相关资源
    最近更新 更多