共计 3499 个字符,预计需要花费 9 分钟才能阅读完成。
欢送关注公众号
如果你用过 TypeScript,肯定接触过 Interface
和Type
。
5 秒钟思考一下,他俩有什么雷同和不同?
如果你对他们的不同无所不知,那么请持续往下看。
如果咱们申明一个 Point
类型,能够通过以下两种形式都会达到咱们想要的后果:
interface Point {
x: number;
y: number;
}
或者
type Point = {
x: number;
y: number;
}
下面的列子没有体现出 interface
和 type
之间的不同。
让咱们进一步摸索。
TypeScript 的类型包含原始数据类型、对象类型、高级类型等。
原始数据类型包含:boolean
、number
、string
、null
、undefined
以及 ES6 中的新类型 Symbol
和 ES10 中的 BigInt
。
高级类型:联结类型(Unions Type),泛型(Generics)
联结类型(Unions Type)
联结类型(Union Types)示意取值能够为多种类型中的一种。
举个栗子:
function printId(id: number | string) {console.log("Your ID is:" + id);
}
// OK
printId(101);
// OK
printId("202");
// Error
printId({myID: 22342});
// 抛出错误信息
//Argument of type '{myID: number;}' is not assignable to parameter of type 'string | number'.
// Type '{myID: number;}' is not assignable to type 'number'.
下面例子中如果删除传入一个对象 会抛出异样,不能把 '{myID: number;}'
赋值给 string 或者 number 类型。
function printId(id: number | string) {console.log(id.toUpperCase());
}
//Error
Property 'toUpperCase' does not exist on type 'string | number'.
Property 'toUpperCase' does not exist on type 'number'.
咱们来剖析一下下面的报错,只有 string
类型的字符串有 toUpperCase
属性。number
类型没有 toUpperCase
属性,ts 类型推断的时候就会报错。感觉 TypeScript 很智能,能够提前感知谬误。
如果想反对参数 既是 string 类型,又是 number 类型,须要改良一下。如下:
function printId(id: number | string) {if (typeof id === "string") {
// In this branch, id is of type 'string'
console.log(id.toUpperCase());
} else {
// Here, id is of type 'number'
console.log(id);
}
}
类型别名(Type Aliases)
类型别名是指给一个类型起个新名字。留神这里不是定义一个新的类型,而是给了一个新的名字。
类型别名罕用于 原始类型,联结类型(Unions 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 ID = number | string;
type UserInputSanitizedString = string;
function sanitizeInput(str: string): UserInputSanitizedString {return "inputcontent"}
类型别名是指给一个类型起个新名字,所以上面 string 和 UserInputSanitizedString 都是雷同类型
对象的类型—接口
在 TypeScript 中,咱们应用接口(Interfaces)来定义对象类型。相比类型别名,Interfaces 仅用于 对象类型。
继承—extend
interface
和 type
都反对继承,并且 interface
能够继承 type
,type
又能够继承interface
,只是语法不一样。举例说明:
1.interface
extend interface
interface PartialPointX {x: number;}
interface Point extends PartialPointX {y: number;}
2.interface
extend type
type PartialPointX = {x: number;};
interface Point extends PartialPointX {y: number;}
type
&type
type PartialPointX = {x: number;};
// 这里继承应用的是 &
type Point = PartialPointX & {y: number;};
type
&interface
interface PartialPointX {x: number;}
type Point = PartialPointX & {y: number;};
实现—Implements
一个 class 能够实现 (implement) interface 和 type,但不能够实现(implement) 一个 联结类型(unions type)
interface Point {
x: number;
y: number;
}
class SomePoint implements Point {
x = 1;
y = 2;
}
type AnotherPoint = {
x: number;
y: number;
};
class SomePoint2 implements AnotherPoint {
x = 1;
y = 2;
}
type PartialPoint = {x: number;} | {y: number;};
// 不能实现一个联结类型,上面代码将会抛出异样
class SomePartialPoint implements PartialPoint {
x = 1;
y = 2;
}
申明合并—Declaration Merging
TypeScript 在编译的时候,会将名字雷同的 interface
合并成一个接口,然而 type
就不行。
看一个简略的例子,interface 名字一样,然而 属性名不同
interface Box {
height: number;
width: number;
}
interface Box {scale: number;}
let box: Box = {height: 5, width: 6, scale: 10};
下面的例子 把两个 Box 的类型合并成了上面后果
interface Box {
height: number;
width: number;
scale: number;
}
let box: Box = {height: 5, width: 6, scale: 10};
再来看一个例子,interface 名字一样,然而 属性名也一样
interface Cloner {clone(animal: Animal): Animal;
}
interface Cloner {clone(animal: Sheep): Sheep;
}
interface Cloner {clone(animal: Dog): Dog;
clone(animal: Cat): Cat;
}
三个 Cloner 的 interface 合并之后的后果如下:
interface Cloner {clone(animal: Dog): Dog;
clone(animal: Cat): Cat;
clone(animal: Sheep): Sheep;
clone(animal: Animal): Animal;
}
仔细观察,合并之后,第三个接口的属性排在最后面,优先级最高。这个肯定要留神
Interface
和 Type
如何抉择呢?
下面内容,咱们比拟了 Interface
和Type
两者之间的相同点和不同点。接下来总结一下。
对于库中类型或第三方库类型,定义公共 API,应应用接口来提供申明合并性能。
除此之外,咱们轻易抉择,然而要保障代码的一致性。
参考资料
https://www.typescriptlang.or…
https://javascript.plainengli…