简体   繁体   English

Typescript 具有动态属性名称

[英]Typescript with dynamic property names

Is there any way in typescript to have a property name generated dynamically by modifying another property name? typescript 中是否有任何方法可以通过修改另一个属性名称来动态生成属性名称?

I'm trying to write some typings for a React higher order component that modifies the props passed to a wrapped component.我正在尝试为 React 高阶组件编写一些类型,以修改传递给包装组件的道具。 If you configure the hoc with a property name (eg value ) it will also generate a property name from that (in this case, defaultValue ).如果您使用属性名称(例如value )配置 hoc,它还将从中生成一个属性名称(在本例中为defaultValue )。

A sample of partially working code on the Typescript playground . Typescript 操场上的部分工作代码示例。

Ideally, there would be no error when attempting to access defaultValue .理想情况下,尝试访问defaultValue时不会出错。

This was not possible back when you asked this question, but it is possible now with the introduction of Template Literal Types in typescript version 4.1.当您问这个问题时,这是不可能的,但是现在在 typescript 版本 4.1 中引入Template Literal Types是可能的。

We define a type that maps from a string literal "name" to its corresponding "defaultName".我们定义了一个从字符串文字“name”映射到其对应的“defaultName”的类型。

type DefaultName<PropName extends string> = `default${Capitalize<PropName>}`

We declare the Props should have values for both the property and its default.我们声明Props应该具有属性及其默认值的值。

type Props<PropName extends string, Value = boolean> = {
    [K in PropName]: Value;
} & {
    [K in DefaultName<PropName>]: Value;
}

I moved the manipulation of the string into a separate function which asserts the correct return type for the string literal which it creates.我将字符串的操作移动到一个单独的 function 中,它为它创建的字符串文字断言正确的返回类型。 (Though technically, the hoc works without this assertion due to the as Props<PropName> ). (虽然从技术上讲,由于as Props<PropName> ,临时工作没有这个断言)。

function computeName<T extends string>(name: T): DefaultName<T> {
    const computedName = 'default' + name.slice(0, 1).toUpperCase() + name.slice(1);
    // need to assert the return type here, otherwise it's just `string`
    return computedName as DefaultName<T>;
}

Your hoc is basically the same.你的hoc基本上是一样的。 We still need to assert as Props<PropName> when calling fn , otherwise the object gets interpreted as { [x: string]: boolean; }我们仍然需要在调用fn时声明as Props<PropName> ,否则 object 将被解释为{ [x: string]: boolean; } { [x: string]: boolean; } . { [x: string]: boolean; }

function hoc<PropName extends string>(config: Config<PropName>, fn: Callback<PropName>) {
    fn({
        [config.name]: true,
        [computeName(config.name)]: false
    } as Props<PropName>);
}

The magic happens in test , where now obj is known to have a property obj.defaultValue .魔法发生在test ,现在obj有一个属性obj.defaultValue This fixes the error that you had before.这修复了您之前遇到的错误。

const test = hoc({ name: 'value' }, (obj) => {
    console.log(obj.value, obj.defaultValue); // no more errors
});

Typescript Playground Link Typescript 游乐场链接

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

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