一、交叉类型(Intersection Types)【&】
交叉类型是将多个类型合并为一个类型
Person & Serializable & Loggabl
二、联合类型(Union Types)【|】
联合类型表示一个值可以是几种类型之一。 我们用竖线(|)分隔每个类型,所以number | string | boolean表示一个值可以是number,string,或boolean。
interface Bird {fly();layEggs();}interface Fish {swim();layEggs();}function getSmallPet(): Fish | Bird {// ...}let pet = getSmallPet();pet.layEggs(); // okaypet.swim(); // errors
三、类型保护与区分类型(Type Guards and Differentiating Types)
1.类型断言
联合类型适合于那些值可以为不同类型的情况。为了使用独有成员变量,要使用类型断言:
let pet = getSmallPet();if ((<Fish>pet).swim) {(<Fish>pet).swim();}else {(<Bird>pet).fly();}
2. 用户自定义的类型保护
类型保护就是一些表达式,它们会在运行时检查以确保在某个作用域里的类型。
function isFish(pet: Fish | Bird): pet is Fish {return (<Fish>pet).swim !== undefined;}// pet is Fish就是类型谓词。// 谓词为parameterName is Type这种形式,// parameterName必须是来自于当前函数签名里的一个参数名。
每当使用一些变量调用isFish时,TypeScript会将变量缩减为那个具体的类型,只要这个类型与变量的原始类型是兼容的。
3.typeof类型保护
typeof x === "number"
4.instanceof类型保护
_instanceof_类型保护是通过构造函数来细化类型的一种方式instanceof的右侧要求是一个构造函数,TypeScript将细化为:
- 此构造函数的
prototype属性的类型,如果它的类型不为any的话 - 构造签名所返回的类型的联合
四、可以为null的类型
默认情况下,类型检查器认为null与undefined可以赋值给任何类型。null与undefined是所有其它类型的一个有效值--strictNullChecks标记可以解决此错误:当你声明一个变量时,它不会自动地包含null或undefined
1. 可选参数和可选属性
使用了--strictNullChecks,可选参数会被自动地加上| undefined:``
2. 类型保护和类型断言
可以为null的类型是通过联合类型实现,那么你需要使用类型保护来去除null
if (sn == null) {return "default";}sn || "default";
你可以使用类型断言手动去除。 语法是添加!后缀:identifier!从identifier的类型里去除了null和undefined:
name!.charAt(0)
五、类型别名
类型别名有时和接口很像,但是可以作用于原始值,联合类型,元组以及其它任何你需要手写的类型。
type Name = string;type NameResolver = () => string;type NameOrResolver = Name | NameResolver;
起别名不会新建一个类型 - 它创建了一个新名字来引用那个类型
然而,类型别名不能出现在声明右侧的任何地方
type Yikes = Array<Yikes>; // error
1. 接口 vs. 类型别名
- 其一,接口创建了一个新的名字,可以在其它任何地方使用
另一个重要区别是类型别名不能被
extends和implements自己也不能extends和implements其它类型另一方面,如果你无法通过接口来描述一个类型并且需要使用联合类型或元组类型,这时通常会使用类型别名。
六、字符串字面量类型
字符串字面量类型允许你指定字符串必须的固定值。
type Easing = "a" | "b" | "c";
七、数字字面量类型
八、可辨识联合(Discriminated Unions)
你可以合并单例类型,联合类型,类型保护和类型别名来创建一个叫做可辨识联合的高级模式,它也称做标签联合或代数数据类型。
具有普通的单例类型属性—可辨识的特征。
- 一个类型别名包含了那些类型的联合—联合。
此属性上的类型保护。
interface Square {kind: "square";size: number;}interface Rectangle {kind: "rectangle";width: number;height: number;}interface Circle {kind: "circle";radius: number;}// kind属性称做可辨识的特征或标签type Shape = Square | Rectangle | Circle;function area(s: Shape) {switch (s.kind) {case "square": return s.size * s.size;case "rectangle": return s.height * s.width;case "circle": return Math.PI * s.radius ** 2;}}
1. 完整性检查
// 给Shape添加一个属性Triangle// 此时function area不能正确返回所有的
首先是启用
--strictNullChecks并且指定一个返回值类型:
因为switch没有包涵所有情况,所以TypeScript认为这个函数有时候会返回undefined
- 第二种方法使用
never类型,编译器用它来进行完整性检查:function assertNever(x: never): never {throw new Error("Unexpected object: " + x);}function area(s: Shape) {switch (s.kind) {case "square": return s.size * s.size;case "rectangle": return s.height * s.width;case "circle": return Math.PI * s.radius ** 2;default: return assertNever(s); // error here if there are missing cases}}
九、索引类型(Index types)
function pluck<T, K extends keyof T>(o: T, names: K[]): T[K][] {return names.map(n => o[n]);}
索引类型和字符串索引签名
keyof和T[K]与字符串索引签名进行交 ```typescript interface Map{
[key: string]: T;
}
let keys: keyof Map
<a name="hukrL"></a># 十、映射类型一个常见的任务是将一个已知的类型每个属性都变为可选的,或者我们想要一个只读版本:<br />TypeScript提供了从旧类型中创建新类型的一种方式 — **映射类型**```typescripttype Readonly<T> = {readonly [P in keyof T]: T[P];}type Partial<T> = {[P in keyof T]?: T[P];}// 使用type PersonPartial = Partial<Person>;type ReadonlyPerson = Readonly<Person>;
