如何在 TypeScript 中动态添加属性到一个接口?

huangapple go评论69阅读模式
英文:

How do I dynamically add attributes to an interface in typescript?

问题

可以在 TypeScript 中实现上面的需求,以下是代码示例:

type Add<T, K, V> = T & { [P in K]: V };

interface Container { }

type ResultContainer = Add<Container, "name", string>;
type FinalContainer = Add<ResultContainer, "age", number>;

这将创建一个名为 FinalContainer 的接口,它包含了所需的属性 nameage

英文:

I have an interface:

interface Container {

}
// I want to do the following
Add&lt;Container, &quot;name&quot;, string&gt;
Add&lt;Container, &quot;age&quot;, number&gt;

// Here are the results I hope to get
interface Container {
    name: string
    age: number
}

Is it possible to implement the above in typescript?

答案1

得分: 0

以下是翻译好的内容:

不可能以 Add&lt;T, K, V&gt; 形式的内容修改传递给 T 的类型参数的声明,无论 Add 是否是一个泛型类型(例如,type Add&lt;T, K, V&gt; = ⋯; type Foo = Add&lt;Container, &quot;name&quot;, string&gt;;)还是一个实例化表达式(例如,function Add&lt;T, K, V&gt;(⋯){⋯}; const foo = Add&lt;Container, &quot;name&quot;, string&gt;;

TypeScript 提供的唯一修改现有接口类型声明的方式是通过声明合并,在其中重新声明接口并添加新属性:

interface Container { name: string }
// 稍后
interface Container { age: number }

const c: Container = { name: "abc", age: 123 }; // 可行
c.name.toUpperCase(); // 可行
c.age.toFixed(); // 可行

但没有办法使用用户定义的代码来抽象出声明合并操作。我找不到关于这方面的任何现有功能请求在TypeScript的问题列表中,所以我无法指向一个官方来源来证明这是不可能的。如果有人提出这样的问题,那么我们可以听取来自TypeScript团队的官方回应,但我想这个问题很可能会被迅速拒绝。

Playground代码链接

英文:

It is not possible for something of the form Add&lt;T, K, V&gt; to modify the declaration of the type argument passed in as T, whether Add is a generic type (e.g., type Add&lt;T, K, V&gt; = ⋯; type Foo = Add&lt;Container, &quot;name&quot;, string&gt;;) or an instantiation expression (e.g., function Add&lt;T, K, V&gt;(⋯){⋯}; const foo = Add&lt;Container, &quot;name&quot;, string&gt;;)

The only facility TypeScript provides to modify the declaration of an existing interface type is via declaration merging, where you re-declare the interface and add new properties to it:

interface Container { name: string }
// later
interface Container { age: number }

const c: Container = { name: &quot;abc&quot;, age: 123 }; // okay
c.name.toUpperCase(); // okay
c.age.toFixed(); // okay

But there is no way to abstract over the declaration merging operation with user-defined code. I can't find any existing feature request for this in TypeScript's issue list, so I can't direct you to an authoritative source saying this is impossible. If one were to file such an issue then we could hear official word from the TypeScript team, but I imagine the issue would be swiftly declined.

Playground link to code

huangapple
  • 本文由 发表于 2023年7月18日 10:36:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/76709199.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定