TypeScript 添加 kebab 大小写类型形成实际的驼峰大小写键

mad*_*man 8 typing typescript typescript-typings

这是一个示例输入界面

export interface CssProperties {
    alignContent: number | string | null;
    alignItems: number | string | null;
    alignSelf: number | string | null;
    alignmentBaseline: number | string | null;
}
Run Code Online (Sandbox Code Playgroud)

结果类型应该如下所示。

-> 添加烤肉串盒类型

export interface CssProperties {
    align-content: number | string | null;
    alignContent: number | string | null;
    align-items: number | string | null;
    alignItems: number | string | null;
    align-self: number | string | null;
    alignSelf: number | string | null;
    alignment-baseline: number | string | null;
    alignmentBaseline: number | string | null;
}
Run Code Online (Sandbox Code Playgroud)

jca*_*alz 17

更新为 TS4.5+

现在 TypeScript 支持条件类型的尾递归消除,我们可以Kebab<T>用一种简单的方式编写,该方式应该处理最多 1000 个字符的字符串:

type Kebab<T extends string, A extends string = ""> =
    T extends `${infer F}${infer R}` ?
    Kebab<R, `${A}${F extends Lowercase<F> ? "" : "-"}${Lowercase<F>}`> :
    A
Run Code Online (Sandbox Code Playgroud)

这是通过逐个字符迭代,并"-"在每个还不是小写的字符之前插入一个(因此像数字这样的无大小写字符前面不会有破折号),然后将每个字符小写。

TypeScript 4.5+ 中的非尾递归逐字符迭代,或 TypeScript 4.4 及以下版本中的任何递归类型都会达到适度长字符串的递归限制,有时甚至只有二十个左右字符的字符串,并且需要奇怪的解决方法来处理更长的字符串。但现在我们可以处理的字符串文字比我想象的任何人合理需要的时间都要长:

type Testing = Kebab<"itWasTheBestOfTimesItWasTheWorstOfTimesItWasTheAgeOfWisdomItWasTheAgeOfFoolishnessItWasTheEpochOfBeliefItWasTheEpochOfIncredulityItWasTheSeasonOfLightItWasTheSeasonOfDarknessItWasTheSpringOfHopeItWasTheWinterOfDespair">
// type Testing = "it-was-the-best-of-times-it-was-the-worst-of-times-it-was-the-age-of-wisdom-it-was-the-age-of-foolishness-it-was-the-epoch-of-belief-it-was-the-epoch-of-incredulity-it-was-the-season-of-light-it-was-the-season-of-darkness-it-was-the-spring-of-hope-it-was-the-winter-of-despair"
Run Code Online (Sandbox Code Playgroud)

现在我们可以使用键重新映射(也是 TS4.1 的一项功能)轻松地将具有驼峰命名法键的对象转换为具有短横线命名法键的对象:

type KebabKeys<T> = { [K in keyof T as K extends string ? Kebab<K> : K]: T[K] };
Run Code Online (Sandbox Code Playgroud)

最后,让我们在您的示例中尝试一下:

export interface CssPropertiesCamel {
    alignContent: number | string | null;
    alignItems: number | string | null;
    alignSelf: number | string | null;
    alignmentBaseline: number | string | null;
}    

type CssPropertiesKebab = KebabKeys<CssPropertiesCamel>;
/* type CssPropertiesKebab = {
    "align-content": number | string | null;
    "align-items": number | string | null;
    "align-self": number | string | null;
    "alignment-baseline": number | string | null;
} */

export interface CssProperties extends CssPropertiesCamel, CssPropertiesKebab { }
Run Code Online (Sandbox Code Playgroud)

看起来不错!我们已经CssPropertiesCamel变成CssPropertiesKebab, 然后CssProperties可以是这两种类型的合并版本。

Playground 代码链接


小智 0

如果您只是想将带连字符的 CSS 属性添加到React.CSSProperties,您可以通过模块增强来完成此操作。

在根目录中创建一个名为的文件css.d.ts并使用以下内容:

declare module "csstype" {
  interface Properties extends PropertiesHyphen {}
}
Run Code Online (Sandbox Code Playgroud)

更多文档在这里: https: //github.com/frenic/csstype#usage

这是有效的,因为 Reactcsstype在底层使用了它的CSSProperties类型。