官方文档中有关于两者对比的信息,隐藏在 TypeScript Handbook 中,见 Interfaces vs. Type Aliases 部分。

但因为这一部分很久没更新了,所以其中描述的内容不一定全对。

比如,

区别点之一:Type Alias 不会创建新的类型,体现在错误信息上。

One difference is, that interfaces create a new name that is used everywhere. Type aliases don’t create a new name — for instance, error messages won’t use the alias name.

不完全正确。直接通过 type 定义的初始类型,是会创建相应的类型名称的。

什么意思呢。就是说,不是使用 &, | 等操作符创建的 union type 及 intersection type。

type Person = {
name: string;
age: number;
}; // [x] Property 'age' is missing in type '{ name: string; }' but required in type 'Person'.ts(2741)

const bob: Person = {

name: "bob"

};

注意这里错误信息使用的是类型 Person 而不是对应的 plain object 对象。

区别点之二:type alias 不能被 extendsimplements

实际上在扩展和实现上二者已经没有区别,甚至可以混用,比如让一个 class 同时实现 interface 和 type alias 定义的类型。

type PointType = {
x: number;
y: number;
}; interface PointInterface {

a: number;

b: number;

} class Shape implements PointType, PointInterface {

constructor(public a = 1, public b = 2, public x = 3, public y = 4) {}

}

区别点之三:type alias 不能扩展和实现其他类型

不完全正确。因为通过正交操作符(intersection type) & 可以达到 extends 的目的。

interface Person {
name: string;
} interface Job {

title: string;

} type EmployeeType = Person & Job; class Employee implements EmployeeType {

constructor(public name = "Nobody", public title = "Noone") {}

}

上面可以看到,两者大部分情况下不用过多区分。

在使用了 union type 的时候,一些区别才开始显现。其实也算不得区别,因为只有 type alias 可通过 union type 定义。

当 type 包含 union type 时,该类型是不能被实现和扩展的。

interface Triangle {
area: number;
} interface Square {

width: number;

height: number;

} type ShapeType = Triangle | Square; // [x] An interface can only extend an object type or intersection of object types with statically known members.ts(2312)

interface MyShape extends ShapeType; class Shape implements ShapeType{

// [x] A class can only implement an object type or intersection of object types with statically known members.ts(2422)

}

因为 union type 描述的是一个或者的状态,一个类不可能即是此类型也是另外种类型。interface 也不可能继承一个类型还不确定的类型。

类型合并

最明显的一点区别,是在进行类型合并(Declaration Merging)的时候,type alias 是不会被合并的,而同名的多个 interface 会合并成一个。

interface Person {
name: string;
}
interface Person {
age: number;
} const person: Person = {

name: "Bob",

age: 9

};

对于 type alias,存在同名时直接报错。

type Person {  // [x] Duplicate identifier 'Person'.ts(2300)
name: string;
}
type Person { // [x] Duplicate identifier 'Person'.ts(2300)
age: number;
}

明白这点对于三方库的作者来说很重要。假如你写了个 npm 包,导出的是 type,则使用者无法通过简单定义同名类型来进行扩充。

所以,写库的时候,尽量使用 interface。

结论

官方推荐用 interface,其他无法满足需求的情况下用 type alias。

但其实,因为 union type 和 intersection type 是很常用的,所以避免不了大量使用 type alias 的场景,一些复杂类型也需要通过组装后形成 type alias 来使用。所以,如果想保持代码统一,可尽量选择使用 type alias。通过上面的对比,type alias 其实可函盖 interface 的大部分场景。

对于 React 组件中 props 及 state,使用 type alias,这样能够保证使用组件的地方不能随意在上面添加属性。如果有自定义需求,可通过 HOC (Higher-Order Components)二次封装。

编写三方库时使用 interface,其更加灵活自动的类型合并可应对未知的复杂使用场景。

相关资料

TypeScript: type alias 与 interface的更多相关文章

  1. is not valid JSON: json: cannot unmarshal string into Go value of type map[string]interface | mongodb在windows和Linux导出出错

    执行mongoexport命令的时候 mongoexport --csv -f externalSeqNum,paymentId --host 127.0.0.1:27017 -d liveX -c ...

  2. 解决 Could not resolve type alias 'com.deppon.gis.module.job.server.util.SdoGeometryTypeHandler'. 的办法

    单元测试提示下面错误: 核心错误: Failed to parse mapping resource: 'file [D:\490993\安装程序\DPAP2.1\dpap_v2.0.1\dpap_v ...

  3. The repository for high quality TypeScript type definitions

    Best practices This is a guide to the best practices to follow when creating typing files. There are ...

  4. [TypeScript] Type Definitions and Modules

    For example you are building your own module, the same as Lodash: my-lodash.d.ts declare module &quo ...

  5. TypeScript 高级类型 接口(interface)

    在代码的实现或者调用上能设定一定的限制和规范,就像契约一样.通常,我们把这种契约称为接口. TypeScript的核心原则之一是对值所具有的结构进行类型检查. 有时称为“鸭式辨型法”或“结构性子类型化 ...

  6. TypeScript Type Compatibility(类型兼容)

    TypeScript中的类型兼容是基于结构归类的.在普通分类的相比之下,结构归类是一种纯粹用于将其成员的类型进行关联的方法.思考下面的代码: interface Named { name: strin ...

  7. TypeScript Type Innference(类型推断)

    在这一节,我们将介绍TypeScript中的类型推断.我们将会讨论类型推断需要在何处用到以及如何推断. 基础 在TypeScript中,在几个没有明确指定类型注释的地方将会使用类型推断来提供类型信息. ...

  8. Typescript中的class interface 只是在声明,其实什么也没有干!

    由于vue.js的特殊机制,初始化后给对象添加的属性是无法更新UI的. 最近结合typescript和vue进行web开发,就遇到了这样的坑. class user{ name:string; age ...

  9. 6.mybatis异常:SQL Mapper Configuration,Error parsing Mapper XML,Could not resolve type alias

    在xxxMapper中 <select id="getClazz" parameterType="int" resultType="getCla ...

随机推荐

  1. Codeforces 446A. DZY Loves Sequences (线性DP)

    <题目链接> 题目大意: 给定一个长度为$n$的序列,现在最多能够改变其中的一个数字,使其变成任意值.问你这个序列的最长严格上升子段的长度是多少. #include <bits/st ...

  2. idea通过mapper快速定位到xml文件

    1.点击File找到设置(Settings) 2.点击Plugins下的 Browse respositories 3.在搜索栏搜索mybatis ,选中 Free Mybatis plugin——i ...

  3. SpringBoot使用prometheus监控

    本文介绍SpringBoot如何使用Prometheus配合Grafana监控. 1.关于Prometheus Prometheus是一个根据应用的metrics来进行监控的开源工具.相信很多工程都在 ...

  4. Unity Rain Ai 插件基本使用(二)

    前言 在前面的教程中我们已经基本实现了路径导航和障碍物规避. 但是这样我们并没有让我们的角色学会思考,他只是机械的去完成一些步骤,这并不能体现Rain插件的智能. 一个角色他应该有多个不同的状态,待机 ...

  5. LOJ.6435.[PKUSC2018]星际穿越(倍增)

    LOJ BZOJ 参考这儿qwq. 首先询问都是求,向左走的最短路. \(f[i][j]\)表示从\(i\)走到\(j\)最少需要多少步.表示这样只会\(O(n^2\log n)\)的= =但是感觉能 ...

  6. 微信跳转,手机WAP浏览器一键超级跳转微信指定页面

    微信跳转,手机WAP浏览器一键超级跳转微信指定页面 这篇文章主要介绍了如何在手机浏览器wap网页中点击链接跳转到微信界面,需要的朋友可以参考下 先说第一种,最简单的唤起微信协议,weixin://主流 ...

  7. Python使用ProtoBuffer

    Python使用ProtoBuffer Protocol Buffers,是Google公司开发的一种数据描述语言,类似于XML能够将结构化数据序列化,可用于数据存储.通信协议等方面. 就可读性而言感 ...

  8. vue Error: No PostCSS Config found in

    最近在做一个vue的移动端的项目,遇到一个问题,我本地的项目运行正常,可是上传到github上的一启动就报错,就是标题上的错误,找了很久,刚开始以为是某个css没有配置,就把本地的复制过去还是报错,无 ...

  9. js运算符浅析

    什么是运算符? 连接两个或多个操作数(某个值,表达式)之间的符号. 运算符的分类: 1. 赋值运算符(=) 将右边的值赋给左边. var x = 10; var y = x; console.log( ...

  10. C#嵌套类

    { "children" : [{ "children" : [{ "children" : [], "name" : ...