【问题标题】:Mapping a string to Template Literal Type in TypeScript在 TypeScript 中将字符串映射到模板文字类型
【发布时间】:2021-10-28 20:13:37
【问题描述】:

有没有办法在 TypeScript 中将字符串映射到匹配的模板文字类型?

这是一个例子:

type SomeType<T> = {
  [P in keyof T as `as${Capitalize<string & P>}`]: number;
};

这应该将T 中的每个属性x 变成一个属性asX

但现在我想取一个像 foo 这样的属性名称,然后以 TypeScript 可以检测到的方式将其转换为 asFoo

我希望能够做到这一点:

interface I {
  foo: number;
  bar: number;
}

const obj: SomeType<I> = {
  asFoo: 1,
  asBar: 2,
};

const str = 'foo';
// Doesn't work, trying to capitalize str, but TypeScript only sees it as a string
obj[`as${str[0].toUpperCase()}${str.slice(1)}`];

我想以某种方式获取str 和索引obj。这有可能吗?我想我可以转换字符串,但我不想那样做。

目前我正在通过创建这样的函数来处理这个问题:

function getProperty(key: string): keyof SomeType<I> {
  return key === 'foo' ? 'asFoo' : 'asBar';
}

obj[getProperty('foo')];

但我只是想看看是否有更优雅的解决方案,因为如果有很多属性,这可能会失控。我对 TypeScript 很陌生,所以我可能会遗漏一些东西。

【问题讨论】:

    标签: typescript


    【解决方案1】:

    我通常会尝试将我的逻辑拆分为尽可能小的部分。考虑这个例子:

    type SomeType<T> = {
        [P in keyof T as `as${Capitalize<string & P>}`]: number;
    };
    
    interface Obj {
        foo: number;
        bar: number;
    }
    
    const obj: SomeType<Obj> = {
        asFoo: 1,
        asBar: 2,
    };
    
    
    const capitalize = <Key extends string>(key: Key) =>
        `${key[0].toUpperCase()}${key.slice(1)}` as Capitalize<Key>
    
    const withPrefix = <Key extends string>(key: Key): `as${Key}` => `as${key}`
    
    const getProperty = <Key extends string>(key: Key) => withPrefix(capitalize(key))
    
    
    const result = getProperty('foo') // asFoo
    
    const getter = obj[result] // number
    
    

    Playground

    as${Capitalize&lt;string &amp; P&gt;} 这一行包含两个动作:

    1. 大写,

    2. 添加as前缀

    这就是我使用两个函数的原因

    您可能已经注意到,withPrefixgetProperty 可能是组合的:

    import { compose } from 'redux'
    
    
    const capitalize = <Key extends string>(key: Key) =>
        `${key[0].toUpperCase()}${key.slice(1)}` as Capitalize<Key>
    
    const withPrefix = <Key extends string>(key: Key): `as${Key}` => `as${key}`
    
    type Fn =
        <Key extends string>(key: Key) => `as${Capitalize<Key>}`
    
    const getProperty =
        compose(withPrefix, capitalize) as Fn
    
    const result = getProperty('foo') // asFoo
    

    但它要求您使用额外的 compose 函数和类型断言。

    您可以了解更多关于模板文字字符串from docs

    【讨论】:

    • 哇,那里有一些疯狂的巫术!我不知道这是可能的。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-19
    • 1970-01-01
    • 1970-01-01
    • 2021-11-23
    • 2023-02-07
    • 1970-01-01
    相关资源
    最近更新 更多