简体   繁体   English

TypeScript 泛型类型参数是通过函数推断出来的,而不是类型?

[英]TypeScript generic type parameters are inferred with functions, but not type?

Consider this:考虑一下:

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

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

I have to specify the union of the keys as the generic type argument when creating foobar , which is redundant.创建foobar ,我必须将键的联合指定为泛型类型参数,这是多余的。 I can't figure any way around this.我想不出任何办法来解决这个问题。 But if I write a do-nothing function:但是如果我写一个什么都不做的函数:

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

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

then const foobarInferred is correctly typed as SpecificKeys<"foo" | "bar">那么 const foobarInferred被正确键入为SpecificKeys<"foo" | "bar"> SpecificKeys<"foo" | "bar"> and I didn't have to repeat myself by enumerating all the keys. SpecificKeys<"foo" | "bar">我不必通过枚举所有键来重复自己。

Is there any way to achieve inference of a generic type parameter when creating a typed variable without having to make a do-nothing function?在创建类型化变量时,有什么方法可以实现对泛型类型参数的推断,而不必创建无所作为的函数?

Answer is no.答案是否定的。 Type restricts the value, saying a:T means value a needs to be a member of type T , if not - then compile error.类型限制值,说a:T意味着值a需要是类型T的成员,如果不是 - 则编译错误。 What you want is to say a: infer me typeof a , so in other way round.你想要的是说a: infer me typeof a ,所以a: infer me typeof a

Type annotations is for restricting the value, not value to restrict the type.类型注解是用来限制值的,而不是用来限制类型的值。 TS allows for taking type from the value, but it not allows for taking the type of the value and restricting it at once. TS 允许从值中获取类型,但它不允许获取值的类型并立即对其进行限制。


Still, we can make some tricks to make it working.不过,我们可以制作一些技巧来使其工作。 Consider type level solution:考虑类型级解决方案:

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 操场

Both values foobar and badfoobar are inferred by TS properly without any type annotations.foobarbadfoobar都由 TS 正确推断,没有任何类型注释。 The next thing is calling type level MakeSpecificKeys which is kinda id function you have made before, but this one is at the type level, it restricts the argument type in the same way makeSpecificKeys was doing it.接下来是调用类型级别MakeSpecificKeys ,这是您之前创建的一种 id 函数,但这是在类型级别,它以与makeSpecificKeys相同的方式限制参数类型。 For the badfoobar it shows compile error.对于badfoobar它显示编译错误。

What I have shown here is undoubtedly worst approach then value constructor makeSpecificKeys you have made.我在这里展示的无疑是最糟糕的方法,然后是您所做的值构造函数makeSpecificKeys So stick to that.所以坚持下去。 The one single point of using above approach is that nothing from it goes to the runtime, when makeSpecificKeys does.使用上述方法的一点是,当makeSpecificKeys这样做时,它不会进入运行时。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM