首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >作为泛型参数的类型记录模板文字

作为泛型参数的类型记录模板文字
EN

Stack Overflow用户
提问于 2022-09-20 17:47:37
回答 1查看 98关注 0票数 2

我有一个API,它以类似的形式返回一个对象:

代码语言:javascript
复制
{
  foo: number,
  foo_comment: string,
  foo_formatted_value: string,
  _foo_created_by: string
  bar: number,
  bar_comment: string,
  bar_formatted_value: string,
  _bar_created_by: string
}

看看这个答案,看起来我可以创建一个泛型,在对象的键中添加一个前缀。是否有一种方法可以使泛型以相同的方式接受模板文字参数?

我在想这样的事情:

代码语言:javascript
复制
type Data = {
  foo: number,
  bar: number
}

type Template<T, TemplateFunction extends TemplateLiteralFunction,  V = void> = {
  [K in keyof T as K extends string ? TemplateFunction(K) : never]: (V extends void? T[K]: V)
}

type DataAndMetaData = 
      Data &
      Template<Data,`${1}_comment`>&
      Template<Data,`${1}_formatted_value`>&
      Template<Data,`_${1}_created_by`>;

当然,${1}是不起作用的部分。也许如果有类型生成函数:(Key:string)=>'${Key}...'

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-09-20 18:37:40

您不能以这种方式抽象模板文字类型,但您不需要这样做。相反,您可以使用普通字符串文字类型并使用模板文字类型推断来用所需的键替换您的"${1}"字符串。

看起来可能是这样的:

代码语言:javascript
复制
type Template<T, S extends string, V = void, I extends string = "${1}"> = {
    [K in keyof T as K extends string ?
    S extends `${infer F}${I}${infer R}` ? `${F}${K}${R}` : K :
    K]: V extends void ? T[K] : V;
}

我们可以这样使用它:

代码语言:javascript
复制
type DataAndMetaData =
    Data &
    Template<Data, "${1}_comment" | "${1}_formatted_value" | "_${1}_created_by", string>

/* type DataAndMetaData = Data & {
    foo_comment: string;
    foo_formatted_value: string;
    _foo_created_by: string;
    bar_comment: string;
    bar_formatted_value: string;
    _bar_created_by: string;
}*/

请注意,您可以编写Data & Template<Data, "${1}_comment", string> & Template<Data, "${1}_formatted_value", string> & Template<Data, "_${1}_created_by", string>,但是使用分布型行为一次获得所需的输出类型会更清晰(或者几乎是如此.仍然需要初始的Data & )。

另外,在上面,"${1}"值本质上是任意的,因为我们实际上并没有使用模板文字插值。也许你想用不同的符号来表示要替换的东西。我添加了另一个类型参数I来表示这个值,并使其成为默认设置"${1}"。因此,您可能希望更改默认值,甚至在使用Template时显式设置它。

代码语言:javascript
复制
type Also = Template<Data, "*" | "*_xyz", string, "*">
/* type Also = {
    foo: string;
    foo_xyz: string;
    bar: string;
    bar_xyz: string;
} */

还请注意,上面的定义只执行一个替换,如果包含sigil的多个实例,则会表现得很奇怪:

代码语言:javascript
复制
type Hmm = Template<Data, "${1}_or_not_${1}_that_is_the_question">;
/* type Hmm = {
    "foo_or_not_${1}_that_is_the_question": number;
    "bar_or_not_${1}_that_is_the_question": number;
} */

我假设这并不重要,但如果是这样的话,我们可以编写一个递归版本的替换逻辑来处理它--在另一个问题中,因为它超出了这个问题的范围。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73790777

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档