具有动态属性名称的打字稿

时间:2019-09-24 22:49:56

标签: typescript

打字稿中是否可以通过修改另一个属性名称来动态生成属性名称?

我正在尝试为React高阶组件编写一些类型,以修改传递给包装组件的道具。如果您为hoc配置了属性名称(例如value),它还将从中生成属性名称(在这种情况下为defaultValue)。

Typescript playground上的部分工作代码示例。

理想情况下,尝试访问defaultValue时不会出错。

1 个答案:

答案 0 :(得分:0)

当您问这个问题时,这是不可能的,但现在可以在 typescript 4.1 版中引入 Template Literal Types

我们定义了一个从字符串字面量“name”映射到它对应的“defaultName”的类型。

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

我们声明 Props 应该具有属性及其默认值的值。

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

我将字符串的操作移到一个单独的函数中,该函数为其创建的字符串文字断言正确的返回类型。 (尽管从技术上讲,由于 as Props<PropName>,该 hoc 可以在没有此断言的情况下工作)。

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>;
}

您的 hoc 基本相同。我们仍然需要在调用 as Props<PropName> 时断言 fn,否则对象将被解释为 { [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>);
}

神奇发生在 test 中,现在已知 obj 具有属性 obj.defaultValue。这修复了您之前遇到的错误。

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

Typescript Playground Link