一、交叉类型
定义:将多个类型合并为一个类型,这个类型包含了所有类型的特性
使用符号:&
示例:
function extend<T, U>(first: T, second: U): T & U {
let result = <T & U>{};
for (let id in first) {
(<any>result)[id] = (<any>first)[id];
}
for (let id in second) {
if (!result.hasOwnProperty(id)) {
(<any>result)[id] = (<any>second)[id];
}
}
return result;
}
class Person {
constructor(public name: string) { }
}
interface Loggable {
log(): void;
}
class ConsoleLogger implements Loggable {
log() {
// ...
}
}
var jim = extend(new Person("Jim"), new ConsoleLogger());
var n = jim.name;
jim.log();
二、联合类型
定义:表示一个值可以是几种类型之一
使用符号:竖线( |)分隔每个类型
注意事项:如果一个值是联合类型,我们只能访问此联合类型的所有类型里共有的成员
示例
number | string | boolean表示一个值可以是 number, string,或 boolean
interface Bird {
fly();
layEggs();
}
interface Fish {
swim();
layEggs();
}
function getSmallPet(): Fish | Bird {
// ...
}
let pet = getSmallPet();
pet.layEggs(); // okay
pet.swim(); // errors
三、类型保护
1、用户自定义的类型保护
定义:定义一个函数,它的返回值是一个 类型谓词,谓词为 parameterName is Type这种形式, parameterName必须是来自于当前函数签名里的一个参数名
示例
function isFish(pet: Fish | Bird): pet is Fish {
return (<Fish>pet).swim !== undefined;
}
// 'swim' 和 'fly' 调用都没有问题了
// 使用变量调用 isFish时,TypeScript会将变量缩减为那个具体的类型,
// 只要这个类型与变量的原始类型是兼容的
if (isFish(pet)) {
pet.swim();
}
else {
pet.fly();
}
2、typeof类型保护
(1)TypeScript可以将typeof识别为一个类型保护。 可以直接在代码里检查类型
(2)能被识别为类型保护形式
typeof v === "typename"
typeof v !== "typename"
"typename"必须是 "number", "string", "boolean"或 "symbol"s
示例:
function padLeft(value: string, padding: string | number) {
if (typeof padding === "number") {
return Array(padding + 1).join(" ") + value;
}
if (typeof padding === "string") {
return padding + value;
}
throw new Error(`Expected string or number, got '${padding}'.`);
}
3、instanceof类型保护
instanceof的右侧要求是一个构造函数
object instanceof constructor
instanceof 运算符用来检测 constructor.prototype 是否存在于参数 object 的原型链上
示例
interface Padder {
getPaddingString(): string
}
class SpaceRepeatingPadder implements Padder {
constructor(private numSpaces: number) { }
getPaddingString() {
return Array(this.numSpaces + 1).join(" ");
}
}
class StringPadder implements Padder {
constructor(private value: string) { }
getPaddingString() {
return this.value;
}
}
function getRandomPadder() {
return Math.random() < 0.5 ?
new SpaceRepeatingPadder(4) :
new StringPadder(" ");
}
// 类型为SpaceRepeatingPadder | StringPadder
let padder: Padder = getRandomPadder();
if (padder instanceof SpaceRepeatingPadder) {
padder; // 类型细化为'SpaceRepeatingPadder'
}
if (padder instanceof StringPadder) {
padder; // 类型细化为'StringPadder'
}
四、类型别名
定义:创建了一个新名字来引用那个类型
类型别名使用有时和接口很像
使用规则: 能用 interface 实现,就用 interface , 如果不能就用 type
接口 vs 类型别名:
(1)不同:
类型别名不能被 extends和 implements(自己也不能 extends和 implements其它类型)
无法通过接口来描述一个类型并且需要使用联合类型或元组类型,这时通常会使用类型别名
(一)type 可以而 interface 不行
type 可以声明基本类型别名,联合类型,元组等类型
// 基本类型别名
type Name = string
// 联合类型
interface Dog {
wong();
}
interface Cat {
miao();
}
type Pet = Dog | Cat
// 具体定义数组每个位置的类型
type PetList = [Dog, Pet]
type 语句中还可以使用 typeof 获取实例的 类型进行赋值
// 当你想获取一个变量的类型时,使用 typeof
let div = document.createElement('div');
type B = typeof div
其他操作:
type StringOrNumber = string | number;
type Text = string | { text: string };
type NameLookup = Dictionary<string, Person>;
type Callback<T> = (data: T) => void;
type Pair<T> = [T, T];
type Coordinates = Pair<number>;
type Tree<T> = T | { left: Tree<T>, right: Tree<T> };
(二)interface 可以而 type 不行
interface 能够声明合并
// interface 能够声明合并
interface User {
name: string
age: number
}
interface User {
sex: string
}
/*
User 接口为 {
name: string
age: number
sex: string
}
*/
(2)相同点:
都可以描述一个对象或者函数
interface User {
name: string
age: number
}
interface SetUser {
(name: string, age: number): void;
}
type User = {
name: string
age: number
};
type SetUser = (name: string, age: number)=> void;
都允许拓展, 扩展效果差不多,但是两者语法不同
// interface extends interface
interface Name {
name: string;
}
interface User extends Name {
age: number;
}
// type extends type
type Name = {
name: string;
}
type User = Name & { age: number };
// interface extends type
type Name = {
name: string;
}
interface User extends Name {
age: number;
}
// type extends interface
interface Name {
name: string;
}
type User = Name & {
age: number;
}