我正在学习打字,我想用interface,I've found a blog post来扩展type,这意味着type不可能扩展/实现interfaces.

以下是我想要做的代码示例:

interface IPet {
    needsFood: boolean
}

// How I would like to use the IPet interface with a type, 
type Cat implements IPet = {
    needsFood: boolean,
    color: string,
}

上述代码示例给出了一个错误.'IPet' only refers to a type, but is being used as a value here.

下面是我如何使用Class的iPet界面,但type有可能具有相同的行为吗

class Cat implements IPet {
    needsFood: boolean;
    color: string
}

有没有办法让type实现一个接口?或者,如果我想使用接口,我需要使用Class吗?


Edit:感谢所有的 comments ,我已经更新了一个代码示例的问题.我在这里真正寻找的基本上只是一个是/否的答案,是否有可能让一个类型扩展/实现一个接口.

推荐答案

这个问题的答案是否定的,你不能直接用a type alias来做. implements clause只适用于class声明,extends clause只适用于interfaceclass声明.

当然,获得类似的功能非常容易:


类上的implements子句只是判断类实例是否可分配给声明的类型,如果不是,则生成编译器警告;它对 实例.您可以对实用程序类型执行相同的操作,例如

type Implements<T, U extends T> = U

所以Implements<T, U>对结果类型U没有影响,但是由于UconstrainedT,如果它不可赋值,你会得到一个警告.

让我们来测试一下:

type Cat = Implements<IPet, {
    needsFood: boolean,
    color: string,
}> // okay

type Dog = Implements<IPet, {
    bark(): void 
}>; // error!  Property 'needsFood' is missing in type '{ bark(): void; }'

看上go 不错.


同时,extends子句可用于将成员添加到父类型或缩小父类型的成员范围.这基本上与intersection type相同,因此我们可以创建一个实用程序类型来捕获以下内容:

type Extends<T, U extends Pick<T, keyof T & keyof U>> =
    T & U;

在这里,我们组合了父类型T和新成员U.我对U进行了约束,以确保您不能添加冲突的属性,这类似于您try 扩展具有冲突属性的接口时发生的情况:

type Cat2 = Extends<IPet, {
    color: string
}>

type Dog2 = Extends<IPet, {
    needsFood: number // error! 
}>; // error! 
// Type '{ needsFood: number; }' does not satisfy the constraint Pick<IPet, "needsFood">.

看起来也不错.


这些方法并不完全等同于implements/extends条款,但它们应该足够接近许多用例.几乎可以肯定的是,它们有不同的边缘情况,这些情况可能会被修复或解决.但这里的基本要点是,您可以使用泛型约束和交集类型来构建解决方案.

Playground link to code

Typescript相关问答推荐

如何在不使用变量的情况下静态判断运算式的类型?

使用Angular和API请求在CRUD操作后更新客户端数据的良好实践

如何在函数参数中使用(或模仿)`success`的行为?

如何访问Content UI的DatePicker/中的sx props of year picker?'<>

等待用户在Angular 函数中输入

是否可以基于对象的S属性值[]约束对象的其他属性值用于类型化的对象数组?

TypeScrip省略了类型参数,仅当传递另一个前面的类型参数时才采用默认类型

Cypress页面对象模型模式.扩展Elements属性

一个打字类型可以实现一个接口吗?

Angular 17子路由

布局组件中的Angular 17命名路由出口

为什么我的查询钩子返回的结果与浏览器的网络选项卡中看到的结果不同?

NPM使用Vite Reaction应用程序运行预览有效,但我无法将其部署到Netlify

如何扩展RxJS?

Rxjs将省略的可观测对象合并到一个数组中

无法缩小深度嵌套对象props 的范围

两个名称不同的相同打字界面-如何使其干燥/避免重复?

为什么受歧视的unions 在一种情况下运作良好,但在另一种非常类似的情况下却不起作用?

Typescript 子类继承的方法允许参数中未定义的键

使用 TypeScript 在 SolidJS 中绘制 D3 力图