类型兼容性用于肯定一个类型是否能赋值给其余类型,TypeScript 结构化类型系统的基本规则是,若是 x 要兼容 y,那么 y 至少具备与 x 相同的属性。typescript
interface INamed {
name: string;
}
let x: INamed;
let y = {
name: 'funlee',
age: 18
};
x = y;
复制代码
在考虑函数的兼容性的时候,须要考虑一些额外的东西。ide
要查看 x 是否能赋值给 y,首先看它们的参数列表,x 的每一个参数必须能在 y 里找到对应类型的参数,注意的是参数的名字相同与否无所谓,只看它们的类型。函数
let x = (a: number) => 0;
let y = (b: number, s: string) => 0;
y = x; // OK
x = y; // Error
复制代码
类型系统强制源函数的返回值类型必须是目标函数返回值类型的子类型。ui
interface Point2D {
x: number;
y: number;
}
interface Point3D {
x: number;
y: number;
z: number;
}
let iMakePoint2D = (): Point2D => ({ x: 0, y: 0 });
let iMakePoint3D = (): Point3D => ({ x: 0, y: 0, z: 0 });
iMakePoint2D = iMakePoint3D;
iMakePoint3D = iMakePoint2D; // ERROR: Point2D 不能赋值给 Point3D
复制代码
可选的(预先肯定的)和 Rest 参数(任何数量的参数)都是兼容的:spa
let foo = (x: number, y: number) => {};
let bar = (x?: number, y?: number) => {};
let bas = (...args: number[]) => {};
foo = bar = bas;
bas = bar = foo;
复制代码
枚举与数字类型相互兼容。rest
enum Person {
name,
age,
love
}
let age = Person.age;
let num = 18;
age = num;
num = age;
复制代码
来自于不一样枚举的枚举变量,被认为是不兼容的。code
enum Person {
name,
age,
love
}
enum Colors {
red,
blue,
green
}
let age = Person.age;
let blue = Colors.blue;
// age = blue; // error
复制代码
仅仅只有实例成员和方法会相比较,构造函数和静态成员不会被检查。ip
class Animal {
feet: number;
constructor(name: string, numFeet: number) {}
}
class Size {
feet: number;
constructor(meters: number) {}
}
let a: Animal;
let s: Size;
a = s; // OK
s = a; // OK
复制代码
私有的和受保护的成员必须来自于相同的类。string
class Animal {
protected feet: number;
}
class Cat extends Animal {}
let animal: Animal;
let cat: Cat;
animal = cat; // ok
cat = animal; // ok
class Size {
protected feet: number;
}
let size: Size;
animal = size; // ERROR
size = animal; // ERROR
复制代码
TypeScript 类型系统基于变量的结构,仅当类型参数在被一个成员使用时,才会影响兼容性。以下例子中,T 对兼容性没有影响:it
interface Empty<T> {}
let x: Empty<number>;
let y: Empty<string>;
x = y; // ok
复制代码
当 T 被成员使用时,它将在实例化泛型后影响兼容性:
interface Empty<T> {
data: T;
}
let x: Empty<number>;
let y: Empty<string>;
x = y; // Error
复制代码
若是还没有实例化泛型参数,则在检查兼容性以前将其替换为 any:
let identity = function<T>(x: T): T {
// ...
};
let reverse = function<U>(y: U): U {
// ...
};
identity = reverse; // ok, 由于 `(x: any) => any` 匹配 `(y: any) => any`
复制代码
类中的泛型兼容性与类的兼容性所说起一致:
class List<T> {
add(val: T) {}
}
class Animal {
name: string;
}
class Cat extends Animal {
meow() {
// ..
}
}
const animals = new List<Animal>();
animals.add(new Animal()); // ok
animals.add(new Cat()); // ok
const cats = new List<Cat>();
cats.add(new Animal()); // Error
cats.add(new Cat()); // ok
复制代码