Typescript的数据类型
typescript为了使编写的代码更规范,更有利于维护,增加了类型校验,在typescript中主要提供了以下类型
数据类型
- 布尔类型(boolean)
- 数字类型(number)
- 字符串类型(string)
- 数组类型(array)
- 元组类型(tuple)
- 枚举类型(enum)
- 任意类型(any)
- null 和 undefined
- void类型
- never类型
var flag = true;
flag = 456; // ES5可以这样写,但在typescript中,此处会在编写时报错
// 指定变量类型
var flag:boolean = true; // 布尔类型
var str:string = 'hello'; // 字符串类型
var num1:number = 123; // 数字类型
// any类型可以赋任意类型的值
var num:any = 123;
num = true;
num = 'abc';
// 第1种定义数组的方式
var arr:number[] = [12, 5, 8];
// 第2种定义数组的方式
var arr:Array<number> = [12, 5, 8];
// 元组类型,属于数组的一种,可以为数组中每一个位置元素指定一个类型
let arr:[number, string, string] = [12, "abc","123"];
// 枚举类型
// 枚举类型中间没有等号
enum Flag {success = 1, error = 2};
// 如果定义一个数字枚举,第一个成员初始化为1,其余成员会自动从1开始增长
enum Direction {
Up = 1, // 如果不指定Up初始化值,则 Up的值为0,Down为1
Down, // Up = 1时,Down会自动变成2
Left,
Right
}
// 使用
let s:Flag = Flag.success;
console.log(s); // 输出1
// 如果枚举的标识符没有赋值,打印出来的为前一个的值加1。如果第一项没有值,则第一项值默认为0
enum Color {blue, red, yellow = 3, green, 'white'};
console.log(Color.blue); // 0
console.log(Color.red); // 1
console.log(Color.yellow); // 3
console.log(Color.green); // 4
console.log(Color.white); // 5
// null和undefined 是其他数据类型(never类型)的子类型
// 定义为具体类型的变量,不能为undefined,即不能不初始化一个值。但是定义为undefined类型的变量可以不进行初始化
// 所以可以将变量定义为 具体类型变量 或 undefined类型
var num: number | undefined | null ; // 此时num即可以为空,也可以赋数字的值
// 类似的,一个变量可以定义为多种类型
var a:number | string = 123;
a = 'abc';
// void类型: 表示没有任何类型,一般用于定义方法的时候没有返回值
function run():void{
console.log('run');
}
// 声明一个void类型的变量没有什么作用,因为它只能被赋予undefined和null
let unusable: void = undefined;
// undefined和null类型本身的类型用处不是很大
// never类型: 是其他类型(包括null和undefined)的子类型,代表从不会出现的值,就是说可以把null和undefined赋值给number、string等类型的变量。然而一旦指定了 --strictNullChecks标记,null和undefined就只能赋值给void和它们各自,想给string传入一个null或undefined时需要指定联合类型: string | null | undefined
// 这意味着声明never的变量只能被never类型所赋值
// undefined只能赋值undefined,null只能赋值null
var a:undefined;
a = undefined;
var b:null;
b = null;
// never表示从不会出现的值,例如throw一个错误
// never类型是任何类型的子类型,可以赋值给任何类型
// 没有类型是never类型的子类型或赋值给never类型(除了never本身)
// 一般情况下用不到
// 返回never的函数必须存在无法到达的终点:例如抛出异常、死循环
var c:never;
c = (() =>{
throw new Error('错误');
})();
function infiniteLoop():never {
while(true){
}
}
类型断言
当自己知道某个变量的类型时,可以通过类型断言这种方式告诉编译器。类型断言好比其他语言中的类型转换,但是不进行特殊的数据检查和结构,它没有运行时影响,只在编译阶段起作用。
- 使用尖括号进行类型断言
let someValue: any = 'I konw this is a string';
let strLength: number = (<string>someValue).length; // 使用尖括号断言someValue为string类型
- 使用as进行断言
let someValue: any = 'I konw this is a string';
let strLength: number = (someValue as string).length; // 使用as语法断言someValue为string类型
- 使用感叹号后缀去除类型中的null和undefined ```typescript // indetifier! 从identifier类型中去除null和undefined
function fixed(name: string | null): string { //本例使用了嵌套函数,因为编译器无法去除嵌套函数的null(除非是立即调用的函数表达式)。 因为它无法跟踪所有对嵌套函数的调用,尤其是你将内层函数做为外层函数的返回值。 如果无法知道函数在哪里被调用,就无法知道调用时 name的类型。 function postfix(epithet: string) { return name!.charAt(0) + ‘. the ‘ + epithet; // ok } name = name || “Bob”; return postfix(“great”); }
-
使用js的(+)操作符把字符串转换成数字
```typescript
let a: string = '123';
let b: number = +a; // 使用加号将字符串转换为数字
交叉类型
交叉类型是将多个类型合并为一个类型。 这让我们可以把现有的多种类型叠加到一起成为一种类型,它包含了所需的所有类型的特性。 例如, Person & Serializable & Loggable
同时是 Person
和 Serializable
和 Loggable
。 就是说这个类型的对象同时拥有了这三种类型的成员
联合类型
联合类型与交叉类型很有关联,但是使用上却完全不同。 偶尔你会遇到这种情况,一个代码库希望传入 number
或 string
类型的参数。
// 联合类型表示一个值可以是几种类型之一。 我们用竖线( |)分隔每个类型,所以 number | string | boolean表示一个值可以是 number, string,或 boolean。
function padLeft(value: string, padding: string | number) {
// ...
}
类型保护
- typeof类型保护
这些
typeof
类型保护只有两种形式能被识别:typeof v === "typename"
和typeof v !== "typename"
,"typename"
必须是"number"
,"string"
,"boolean"
或"symbol"
。 但是TypeScript并不会阻止你与其它字符串比较,语言不会把那些表达式识别为类型保护。
if (typeof padding === "number") {
// ....
}
- instanceof类型保护
instanceof
类型保护是通过构造函数来细化类型的一种方式
if (padder instanceof SpaceRepeatingPadder) {
// ....
}
类型别名
给类型起一个新的名字
type Name = string;
type NameResolver = () => string;
type NameOrResolver = Name | NameResolver; // 联合类型
type Container<T> = { value: T }; // 泛型
type Easing = "ease-in" | "ease-out" | "ease-in-out"; // 字面量类型
// 类型别名中可以使用自己
type Tree<T> = {
value: T;
left: Tree<T>;
right: Tree<T>;
}
// 错误用法:type Yikes = Array<Yikes>;
类别名与交叉类型一起使用:
type LinkedList<T> = T & { next: LinkedList<T> };
interface Person {
name: string;
}
var people: LinkedList<Person>;
var s = people.name;
var s = people.next.name;
var s = people.next.next.name;
var s = people.next.next.next.name;