在 Typescript 中,可以使用泛型添加属性键吗?

Ric*_*ler 2 typescript

在打字稿中,可以使用泛型添加属性键吗?

function f<T extends string>(k: T) {
  return { [k]: 'test'; };
}

const obj = f('foo');
// some how assert that obj.foo exists
Run Code Online (Sandbox Code Playgroud)

我有一个类似于上面的函数,它接收一个键k并使用{[identifier]: 'value'}.


我想知道是否可以捕获字符串文字类型,例如'some-key'/T extends string并在另一种类型中使用文字。像这样的东西:

interface F<T extends string> {
  [T]: SomeRandomType;
  otherKey: string;
  anotherKey: number;
}

interface SomeRandomType { /* ... */ }

const f: F<'bar'> = /* ... */;
f.otherKey; // should work
f.anotherKey; // should work
f.bar; // should work
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?这不可能吗?

Ben*_*son 5

是的,使用映射类型交叉类型的创造性组合是可能的。

您可以使用映射类型对“任意字符串文字键控属性”情况进行建模。

type F<Keys extends string> = {
    [K in Keys] : number;
}

const f : F<'bar'> = null;
f.bar;  // typed as a number
f.wibble;  // type error
Run Code Online (Sandbox Code Playgroud)

请注意,映射类型必须是type声明,而不是interfaces。不要问我有什么区别!

然后是使用相交类型 operator 在顶部分层附加属性的情况&。出于某种原因,您必须为此使用&。您似乎不允许将这些属性声明为同一对象类型的一部分。

type F<Keys extends string> = {
    [K in Keys] : number;
} & {
    additionalKey1 : object;
    additionalKey2 : string;
}
const f : F<'bar'> = null;
f.bar;  // typed as a number
f.additionalKey1;  // typed as an object
Run Code Online (Sandbox Code Playgroud)