javascript - 使用 Typescript 声明字符串结构的最佳方法?

标签 javascript typescript template-literals

假设我有这个 JavaScript 对象:

const myObject = {
   id: 'my_id', // Base value that following value's structures will be depended on (always pascal case). 
   upperID: 'MY_ID', // Uppercase of `id`.
   camelID: 'myId', // Camel case of `id`.
}

我想使用 TypeScript 来确保 id 始终是 pascal 小写。 upperIDcamelID 具有与上述不同的字符串结构的相同“值”。在 TypeScript 中声明此 myObject 类型的最佳方式是什么?

最佳答案

使用提供的 Uppercase<T> 大写字母非常容易实用程序类型。

type CasedIds<ID extends string> = {
    id: ID,
    upperID: Uppercase<ID>
}


const myObject: CasedIds<'my_id'> = {
   id: 'my_id',
   upperID: 'MY_ID',
} as const

See playground


Camel 案例变得棘手。因此,首先您需要一个可以对字符串执行此操作的类型。

可能有几种方法可以做到这一点。这是一个。

type CamelCase<T extends string> =
    T extends `${infer Pre}_${infer Letter}${infer Post}`
        ? `${Pre}${Capitalize<Letter>}${CamelCase<Post>}`
        : T

type TestCamel = CamelCase<'abc_def_ghi'> // 'abcDefGhi'

See playground

让我们来看看这个。

这个泛型以字符串类型作为泛型参数T .然后检查是否 T扩展包含下划线后跟一些字符的特定模式的字符串。

如果是,则从该模式中推断出一些子字符串。推断下划线前的部分为Pre , 下划线后的字符为 Letter字符串的其余部分为 Post .否则,只需按原样使用字符串类型即可。

然后我们可以从 Pre 中创建一个新字符串Letter大写,Post .但可能还有更多下划线,所以我们在 Post 上再次执行整个操作.这是一种递归类型,当没有下划线时停止递归。


剩下的就很简单了:

type CamelCase<T extends string> =
    T extends `${infer Pre}_${infer Letter}${infer Post}`
        ? `${Pre}${Capitalize<Letter>}${CamelCase<Post>}`
        : T

type CasedIds<ID extends string> = {
    id: ID,
    upperID: Uppercase<ID>
    camelID: CamelCase<ID>
}


const myObject: CasedIds<'my_id'> = {
   id: 'my_id',
   upperID: 'MY_ID',
   camelID: 'myId',
} as const

See playground


尽管您可能需要一个函数为您构建这些:

function makeId<T extends string>(id: T): CasedIds<T> {
    return {} as unknown as CasedIds<T> // mock a real implementation
}

const myId = makeId('my_id')
myId.id       // type: 'my_id'
myId.upperID  // type: 'MY_ID'
myId.camelID  // type: 'myId'

See playground

关于javascript - 使用 Typescript 声明字符串结构的最佳方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74382893/

相关文章:

javascript - 为什么当数组元素相同时 Splice 只删除最后一个元素

javascript - 我可以在 typescript 中声明一个静态私有(private)函数吗?

javascript - 延迟执行 ES6 模板文字

javascript - 为什么在 javaScript 中类型转换为字符串时,let 不被识别为关键字?

使用模板文字的 Javascript ES6 console.log 对象

javascript - 如何在不使用相同音频ID的情况下播放从数据库获取的多个音频文件

javascript - Chrome 中的并发 Ajax 请求

php - 这个ajax(带原型(prototype))有什么问题?

JavaScript,循环遍历数组和参数 "object"

javascript - 在 Angular 6 中一一处理 http 响应