一、交叉类型(Intersection Types)
交叉类型是奖多个类型合并为一个类型。这往我们可以把多个现有的多种类型叠加成为一种类型,它包含了所需的所有类型的特性。主要用于多个对象的混合。
例如, Person & Serializable & Loggable
同时是Person
和Serializable
和Loggable
。 就是说这个类型的对象同时拥有了这三种类型的成员。
将多个对象混合成一个交叉类型,这种操作用的情况应该比较少
function extend(first: T, second: U): T & U {
let result = {};
for (let id in first) {
(result)[id] = (first)[id];
}
for (let id in second) {
if (!result.hasOwnProperty(id)) {
(result)[id] = (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();
二、联合类型(UnionTypes)
联合类型与交叉类型很有关联,但是使用上却完全不同。
联合类型,将类型使用 | 关联在一起。
联合类型,可以将一个变量指定为已知的默写类型,可以将函数的返回值指定为已知的默写类型。
当前一个函数需要传入string类型或者number类型,可以使用any,同样更推荐使用联合类型。
function padLeft(value: string, padding: string | number) {
// ...
}
let indentedString = padLeft("Hello world", true); // errors during compilation
返回类型中,使用联合类型
interface Bird {
fly();
layEggs();
}
interface Fish {
swim();
layEggs();
}
function getSmallPet(): Fish | Bird {
// ...
}
let pet = getSmallPet();
pet.layEggs(); // okay
pet.swim(); // errors
对于类型的私有部分
let pet=getSmallPet();
pet.layEggs();
//对于两种类型的个字的特有的方法,编译异常
// pet.fly();
// pet.swim();
1.类型保护与区分类型,使用类型断言处理<>或者as
//使用类型断言,判断类型的理由部分
//使用类型断言,编写代码的时候有代码提示
if((pet).fly){
(pet as Bird).fly();
}else{
(pet).swim();
}
2.用户自定义类型区分,使用 is 谓词
类型判断方法
function isFish(pet: Fish | Bird): pet is Fish {
return (pet).swim !== undefined;
}
谓词为
parameterName is Type
这种形式,
parameterName
必须是来自于当前函数签名里的一个参数名。
只有两种形式能被识别:typeof v === "typename"
和typeof v !== "typename"
,"typename"
必须是"number"
,"string"
,"boolean"
或"symbol"
。 但是TypeScript并不会阻止你与其它字符串比较,语言不会把那些表达式识别为类型保护。
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}'.`);
}
4.instanceof 类型保护
instanceof类型保护是通过构造函数来细化类型的一种方式。
1.instanceof要求判断类型有构造函数,也就是对类类型可判断,如果是接口类型则不能使用
2.编译器会识别instanceof,在编写代码识别的时候,会有自动提示
interface Padder {
getPaddingString(): string;
}
class SpaceRepeatingPadder implements Padder {
repeat: string = '张三丰';
getPaddingString() {
return 'space';
}
}
class StringPadder implements Padder {
age: number = 15,
getPaddingString() {
return 'string';
}
}
function getRandomPadder(): Padder {
return Math.random() < 0.5 ?
new SpaceRepeatingPadder() :
new StringPadder();
}
let padder: Padder = getRandomPadder();
//使用 instanceof 类型保护
//编译器自动识别,写代码时自动根据类型提示
if (padder instanceof SpaceRepeatingPadder) {
console.log(padder.repeat);
}
if (padder instanceof StringPadder) {
console.log(padder.age);
}
5.可以为null的类型,可选参数、可选属性
TypeScript具有两种特殊的类型,null和undefined,它们分别具有值null和undefined. 我们在基础类型一节里已经做过简要说明。 默认情况下,类型检查器认为 null与undefined可以赋值给任何类型。
--strictNullChecks标记可以解决此错误:当你声明一个变量时,它不会自动地包含null或undefined。
默认情况下这个属性不启用。
你可以使用联合类型明确的包含它们:
let s = "foo";
s = null; // 错误, 'null'不能赋值给'string'
let sn: string | null = "bar";
sn = null; // 可以
sn = undefined; // error, 'undefined'不能赋值给'string | null'
使用了
--strictNullChecks
,可选参数会被自动地加上
| undefined
:
默认情况下这个属性是启用的。
function f(x: number, y?: number) {
return x + (y || 0);
}
f(1, 2);
f(1);
f(1, undefined);
f(1, null); // error, 'null' is not assignable to 'number | undefined'
三、类型别名 type
类型别名会给一个类型启一个新的名字。
器别名不会新建一个类型。
类型别名可以使用泛型。
不能被extends和implements扩展。
type Name = string;
type NameResolver = () => string;
type NameOrResolver = Name | NameResolver;
function getName(n: NameOrResolver): Name {
if (typeof n === 'string') {
return n;
}
else {
return n();
}
}
四、字符串字面量类型
字符串字面量类型允许你指定字符串必须的固定值。在实际应用中,字符串字面量类型可以与联合类型,类型保护和类型别名很好的配合。
通过结合使用这些特性,你可以实现类似枚举类型的字符串
type Easing = "ease-in" | "ease-out" | "ease-in-out";
class UIElement {
animate(dx: number, dy: number, easing: Easing) {
if (easing === "ease-in") {
// ...
}
else if (easing === "ease-out") {
}
else if (easing === "ease-in-out") {
}
else {
// error! should not pass null or undefined.
}
}
}
let button = new UIElement();
button.animate(0, 0, "ease-in");
button.animate(0, 0, "uneasy"); // error: "uneasy" is not allowed here
五、可辨识联合(Discriminated Unions)
感觉不太好用。
多态的this类型
多态的this类型表示的是某个包含类或接口的子类型。 这被称做 F-bounded多态性。 它能很容易的表现连贯接口间的继承,比如。 在计算器的例子里,在每个操作之后都返回 this类型:
class BasicCalculator {
public constructor(protected value: number = 0) { }
public currentValue(): number {
return this.value;
}
public add(operand: number): this {
this.value += operand;
return this;
}
public multiply(operand: number): this {
this.value *= operand;
return this;
}
// ... other operations go here ...
}
let v = new BasicCalculator(2)
.multiply(5)
.add(1)
.currentValue();
六、索引类型(Index Types)
暂时忽略
七、映射类型
暂时忽略
更多:
TypeScript 类型兼容性整理
TypeScript 类型推论整理
TypeScript 枚举使用整理