欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

TypeScript:高级类型二

程序员文章站 2022-03-05 23:20:55
...

可以为null的类型

TS具有两种特殊的类型,undefinednull,他们分别具有undefined和null值。就像JS中那样null是对初始化后的未赋值的对象的值,undefined是变量初始化后未赋值的值。TS默认情况下,类型检查其认为null和undefined可以赋值给任何类型。

null和undefined可以赋值给任何类型,会导致我们的程序出现无法想象的错误。null的发明者,都称它们未"价值亿万美金的错误"

未了解决这个,ts的--strictNullChecks标记可以解决此错误:当你声明一个变量时,它不会自动地包含null或undefined。当你确切的需要赋值undefined和null的时候,你可以使用联合类型明确的包含他们。如下例子

let s = "foo";
s = null; //错误,'null'不能赋值给'string'
let sn:string|null = "bar"
sn = null; //可以

sn = undefined; //error,'undefined'不能赋值给'string|null'

注意,按照JavaScript的语义,TypeScript会把 null和 undefined区别对待。 string | null, string | undefined和 string | undefined | null是不同的类型。

可选参数和可选属性

使用了 --strictNullChecks,可选参数会被自动地加上|undefined:

function f(x:number,y?:number) {
	return x + (y||0);
}

f1(1,2);
f(1);
f(1, undefined);
f(1, null); // error, 'null' is not assignable to 'number | undefined'

可选属性同样的会被这样处理

class C {
	a:number;
	b?:number;
}

let c = new C();
c.a = 12;
c.a = undefined; // error, 'undefined' is not assignable to 'number'
c.b = 13;
c.b = undefined; // ok
c.b = null; // error, 'null' is not assignable to 'number | undefined'
类型保护和类型断言

为联合类型去除联合类型中的null和undefined的方法

  • 使用类型保护(if( sn == null) { //… })
  • 使用类型断言(语法是是添加 !后缀: identifier!从 identifier的类型里去除了 null和 undefined:)

类型别名

类型别名会给一个类型起新的名字。类型别名有时和接口很像,但是可以作用于原始值,联合类型,元组以及其他任何你需要手写的类型

//类型Name 是 类型string的别名
type Name = string;

//类型NameResolver 是函数类型()=>string的别名
type NameResolver = () => string;

//类型NameOrResolver 是联合类型 Name|NameResolver的别名
type NameOrResolver = Name|NameResolver;

function getName(n:NameOrResolver):Name {
	if(typeof n == 'string') {
		return n;
	}
	else {
		return n;
	}
}

起别名不会新建一个类型 - 它新建了一个新名字来引用那个类型。给原始类型起别名通常没什么用,尽管可以做为文档的一种形式来使用。

同接口一样,类型别名也可以是泛型 - 我们可以添加类型参数并且在别名声明的右侧传入:

type Container<T> = { value:T };

我们也可以使用类型变量别名来在属性中引用自己:

type Tree<T> = {
    value: T;
    left: Tree<T>;
    right: Tree<T>;
}
接口和别名区别

像我们提到的,类型别名可以像接口一样:然而,仍有一些细微差别。

其一,接口创建了一个新的名字,可以在其他任何地方使用。而类型别名并不创建新的名字,比如错误信息就不会使用别名。

其二就是类型别名不能像类和接口那样,通过extends和implements继承。考虑到软件工程中的可扩展性,应该尽量使用接口去代替别名。

相关标签: TypeScript