type 与 interface
官方文档是这么说的:
For the most part, you can choose based on personal preference, and TypeScript will tell you if it needs something to be the other kind of declaration. If you would like a heuristic, use
interface
until you need to use features fromtype
.大多数情况下,你可以根据个人偏好进行选择,TS 会告诉你是否它是否需要额外的信息去改成另一个声明。如果你想要一个启发式:
使用
interface
一直到你需要使用type
的一些特性。
所以,如果不是项目有额外的规范的话,一般情况下可以使用 inrerface
就够了。
type
一个 type alias
的定义就是:一个任何类型的名字 (a name for any type),其语法如下:
type Point = {
x: number;
y: number;
};
// Exactly the same as the earlier example
function printCoord(pt: Point) {
console.log("The coordinate's x value is " + pt.x);
console.log("The coordinate's y value is " + pt.y);
}
printCoord({ x: 100, y: 100 });
除了基础的使用之外,type 还有这几个 interface 不具备的特性:
-
可声明基础型
type primitiveType = string;
而 interface 因为语法问题,当其被进行声明时,已经是一个对象结构。
同理可推,type 也可以用来声明 tuple——毕竟 tuple 从结构上来说不是一个对象。
-
可声明 union 类型
type type1 = { x: number; }; type type2 = { y: number; }; type unionType = type1 | type2;
这时对 unionType 的断言为
{x: 1}
或是{y:1.11}
,如出现其他的类型则会报错:其实这样的功能对于 primitive 的生命比较有用,interface 也可以使用 optional 选项进行实现。
-
可以用计算式
这是在看另一个项目组的项目时碰到的写法,当时第一个感觉就是……woc 牛逼啊,可太省事情了:
可惜 interface 没法使用这个操作。
-
创建后无法被修改
也就比较像是
Object.freeze()
这种实现吧。type Window = { title: string; }; type Window = { ts: TypeScriptAPI; }; // Error: Duplicate identifier 'Window'.
除此之外,type 的扩展方式使用 &
符号,如:
type Animal = {
name: string;
};
type Bear = Animal & {
honey: boolean;
};
const bear = getBear();
bear.name;
bear.honey;
interface
一个 nterface declaration
的定义就是:另一个命名对象类型的方式 (another way to name an object type),其语法如下:
interface Point {
x: number;
y: number;
}
function printCoord(pt: Point) {
console.log("The coordinate's x value is " + pt.x);
console.log("The coordinate's y value is " + pt.y);
}
printCoord({ x: 100, y: 100 });
可以看到,和使用 type 没什么特别大的区别,这也就是 TS 官方说,先用 interface,遇到 interface 没法满足的功能再使用 type 的原因。
interface 的扩展方式如下:
interface Animal {
name: string;
}
interface Bear extends Animal {
honey: boolean;
}
const bear = getBear();
bear.name;
bear.honey;
与 type 的对比就是,interface 更加的动态,也就是说如果新建一个变量名相同的 interface,TS 会自动对其进行扩展,如:
interface Window {
title: string;
}
interface Window {
ts: TypeScriptAPI;
}
const src = 'const a = "Hello World"';
window.ts.transpileModule(src, {});
总结
TS 的官方推荐是一直使用 interface 一直到 interface 无法满足对 type 的需求,个人看别的项目的感觉是,对于大部分的 data definition(不可变的数据类型,需要传进对象的参数)应该使用 type,其他的情况可以使用 interface。
另外 TS 中的实现还挺乱的,比如说彼此扩展这种事情都是可以实现的:
所以规范化的执行是最重要的事情。