Typescript类型判断之兼容性

一:浅议

引文---

在基于名义类型的类型系统中,数据类型的兼容性或等价性是通过明确的声明和/或类型的名称来决定的

例如在Java中的定义  String string = 'java',我们必须给string显式的生命是String类型的,在TS中,所有的数据类型基本都是结构类型,我们通过new操作符构造出来的数据,都会根据其结构成员来分析出其结构类型;

例如:

class Animal {
  feet: number;
  constructor(name: string, numFeet: number) { }
}

class Dog {
  feet: number;
  constructor(numFeet: number) { }
}

let a: Animal;
let s: Dog;

a = s;  // OK
s = a;  // OK

这里我们可以看出Dog和Animal两个类具有相同的成员属性,因此,基于结构类型系统的TS会检查成功;人为a和s是两种可以互相兼容的数据类型;但在Java中,

class Animal {
	Number feet = 0;
}

class Dog {
	Number feet = 0;
}
class Test {
	public static void main() {
		a = new Animal(); // Error a cannot be resolved to a variable
		b = new Dog() // Error b cannot be resolved to a variable
	}
}

二 类型兼容性

对于原始类型和简单的对象数据类型,兼容性是很好判断的,但是对于函数来说,就会复杂一点,包括

  1. 函数参数的不确定性

引用一个例子

let x = (a: number) => 0;
let y = (b: number, s: string) => 0;

y = x; // OK
x = y; // Error

由于参数的不确定性,在x和y的互相赋值操作出现了不同的情况,TS检查系统在检测函数x判定其有为number类型a的参数类型,函数x为具有b和s两个参数;当x赋值给y的时候,右边的x的参数列表能够在y中找到,并且由于js函数参数长度的不确定性,第二个参数忽略,所以能够赋值成功,当y赋值x的时候,y明确第二个参数为string类型的,而x中没有声明第二个参数的类型,所以赋值错误。

  • 2.枚举

枚举类型与数字类型兼容,并且数字类型与枚举类型兼容。但是不同枚举类型之间是不兼容的

  • 3.类的静态和实例、私有属性

类在声明的时候,即产生了类的本省,也声明了类的实例部分,实例可以用来做类型。 因为类可以创建出类型,所以你能够在允许使用接口的地方使用类。

所以比较两个类类型的对象时,只有实例的成员会被比较。 静态成员和构造函数不在比较的范围内。

此外类的私有成员和受保护成员会影响兼容性。 当检查类实例的兼容时,如果目标类型包含一个私有成员,那么源类型必须包含来自同一个类的这个私有成员。简而言之,不同的类中,只要含有私有或者受保护的成员,就不能单单通过结构类型去判断。即使成员完全一致,但只要没有继承关系,就会影响兼容性。

class Animal {
  feet: number;
  private test: any;
  constructor(name: string, numFeet: number) { }
}

class Dog {
  private sex: any;
  feet: number;
  constructor(numFeet: number) { }
}

let a: Animal;
let s: Dog;

a = s;  // Property 'test' is missing in type 'Dog' but required in type 'Animal'.
s = a;  // Property 'sex' is missing in type 'Animal' but required in type 'Dog'.
  • 4.泛型

对于没指定泛型类型的泛型参数时,并且对结构成员的类型没有影响时,会把所有泛型参数当成any比较。 然后用结果类型进行比较,就像上面第一个例子。

当泛型的泛型参数影响到了结构内部的成员,则会产生不同的兼容性问题。

 

你可能感兴趣的:(JavaScript)