使用字符串变量作为属性名称的动态类型

Cor*_*hin 2 typescript

我希望能够使用作为指定参数之一的属性名称来动态构造类型。虽然可以构造实际的对象,但似乎无法构造实际的类型。我想用这种类型来改变构图

export function mapProp<AssignedType>(value: AssignedType, propertyName: string) {

  type ReturnType = {
    [propertyName]: value
  }; // errors on this line

  return {
    [propertyName]: value
  };
}
Run Code Online (Sandbox Code Playgroud)

发出的错误如下:

类型文字中的计算属性名称必须引用其类型为文字类型或“唯一符号”类型的表达式。

例如游乐场:http : //www.typescriptlang.org/play/#src=%0D%0Aexport%20function%20mapProp%3CAssignedType%3E( value%3A%20AssignedType%2C%20propertyName%3A%20string)%20% 7B% 0D%0A%0D%0A%20%20type%20ReturnType%20%3D%20%7B%0D%0A%20%20%20%20%5BpropertyName%5D%3A%20value%0D%0A%20%20% 7D%3B%0D%0A%0D%0A%20%20return%20%7B%0D%0A%20%20%20%20%5BpropertyName%5D%3A%20value%0D%0A%20%20%7D% 3B%0D%0A%7D

jca*_*alz 5

我认为最接近的是这样的:

export function mapProp<PropertyName extends string, AssignedType>(
  value: AssignedType, 
  propertyName: PropertyName
) {

  type ReturnType = {
    [K in PropertyName]: AssignedType
  }; 
  // equivalent to Record<PropertyName, AssignedType>

  return {
    [propertyName]: value
  } as ReturnType;

}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您将使用映射类型而不是带有索引签名的类型。添加的PropertyName泛型类型参数允许键过去的缩小string,如果你传递一个字符串:

const thing = mapProp(123, "abc");
thing.abc; // number
thing.def; // error
Run Code Online (Sandbox Code Playgroud)

在这种情况下ReturnType,已知等效于{abc: number}。如果您只知道密钥string在编译时是a ,那么您将得到以下信息:

declare const propName: string;
const stuff = mapProp(123, propName);
stuff.abc; // number
stuff.def; // number 
Run Code Online (Sandbox Code Playgroud)

现在ReturnType等效于{[k: string]: number},表示它接受任何string键(并为其number赋值)。这可能不是您想要的,但是在这种情况下,这是编译器可以做的最好的事情。

还要注意,在不使用类型断言(as ReturnType)的情况下,计算后的属性通常以字符串索引而不是更具体的形式结束。当前,这是TypeScript 的设计限制。已经进行了一些尝试来解决这个问题,但是还没有任何语言将其纳入语言。

希望能有所帮助;祝好运!