TypeScript
支持与 JavaScript
几乎相同的数据类型,此外还提供了实用的枚举类型方便我们使用。
let isDone: boolean = false;
和 JavaScript
一样,TypeScript
里的所有数字都是浮点数。 这些浮点数的类型是 number
。 除了支持十进制和十六进制字面量,TypeScript
还支持 ECMAScript 2015
中引入的二进制和八进制字面量。
let decLiteral: number = 6;
let hexLiteral: number = 0xf00d;
let binaryLiteral: number = 0b1010;
let octalLiteral: number = 0o744;
和 JavaScript
一样,可以使用双引号( "
)或单引号('
)表示字符串。
let name: string = "bob";
name = "smith";
同样也可以使用 字符串模板:
let name: string = `Gene`;
let age: number = 37;
let sentence: string = `Hello, my name is ${ name }.
I'll be ${ age + 1 } years old next month.`;
有两种方式定义数组,第一种,在数组元素类型后面使用 []
:
let list: number[] = [1, 2, 3];
第二种,使用数组泛型,Array<元素类型>
:
let list: Array = [1, 2, 3];
Tuple
类型也是一个数组,我们可以用它来表示一个已知元素数量和元素类型的数组。 比如,你可以定义一对值分别为 string
和number
类型的元组。
// Declare a tuple type
let x: [string, number];
// Initialize it
x = ['hello', 10]; // OK
// Initialize it incorrectly
x = [10, 'hello']; // Error
当访问一个已知索引的元素,会得到正确的类型:
console.log(x[0].substr(1)); // OK
console.log(x[1].substr(1)); // Error, 'number' does not have 'substr'
使用索引进行越界访问:
x[3] = 'world'; // Error, Tuple type '[string, number]' of length '2' has no element at index '2'.
调用数组的方法:
x.push("world"); // OK
x.push(true); // Error, Argument of type 'true' is not assignable to parameter of type 'string | number'.
1、使用索引来访问越界元素,编译器会报错误
2、使用
push
方法新增元素,元素的类型必须满足其联合类型
enum
类型是对 javascript
标准数据类型的一个补充。
enum Days { Sun, Mon, Tue, Wed, Thu, Fri, Sat };
默认情况下,枚举成员从 0
开始赋值,每次递增步长为 1
,同时,可以从值到名进行反向映射:
// key -> value
console.log(Days["Sun"] === 0); // true
console.log(Days["Mon"] === 1); // true
console.log(Days["Tue"] === 2); // true
console.log(Days["Sat"] === 6); // true
// value -> key
console.log(Days[0] === "Sun"); // true
console.log(Days[1] === "Mon"); // true
console.log(Days[2] === "Tue"); // true
console.log(Days[6] === "Sat"); // true
同时,我们也可以对枚举项进行手动赋值,当值为 number
类型时,未赋值的枚举项会接着上一个枚举项依次赋值。
enum Days { Sun = 2, Mon, Tue = 5, Wed, Thu, Fri, Sat };
console.log(Days.Sun); // 2
console.log(Days.Mon); // 3
console.log(Days.Tue); // 5
console.log(Days.Wed); // 6
console.log(Days.Thu); // 7
如果枚举项的值有重复的话,typescript
不会提示错误,但是通过 value
获取 key
的话,key
是最后一次的枚举项:
enum Days { Sun = 2, Mon = 2, Tue = 1, Wed, Thu, Fri, Sat };
console.log(Days[2]); // Wed
在使用的时候,最好不要出现覆盖的情况。
手动赋值的枚举项可以不是 number
类型,但是,紧跟着的枚举项必须给初始值,否则会报错。
enum Days { Sun = "s", Mon = 2, Tue = 1, Wed, Thu, Fri, Sat };
枚举类型与数字类型兼容,并且数字类型与枚举类型兼容。不同枚举类型之间是不兼容的。
enum Status { Ready, Waiting };
enum Color { Red, Blue, Green };
let status = Status.Ready;
status = Color.Green; // Error
any
表示可以赋值为任意类型。
let myFavoriteNumber: any = 'seven';
myFavoriteNumber = 7;
针对未声明类型的变量,它会被识别为 any
:
let something;
something = 'seven';
something = 7;
某种程度上来说,void
类型像是与any
类型相反,它表示没有任何类型。当一个函数没有返回值时,你通常会见到其返回值类型是 void
:
function bar(): void {}
如果没有明确的指定类型,那么 TypeScript 会依照类型推论(Type Inference)的规则推断出一个类型。
以下代码虽然没有指定类型,但是会在编译的时候报错:
let myFavoriteNumber = 'seven';
myFavoriteNumber = 7; // error TS2322: Type '7' is not assignable to type 'string'.
事实上,它等价于:
let myFavoriteNumber: string = 'seven';
myFavoriteNumber = 7;
TypeScript 会在没有明确的指定类型的时候推测出一个类型,这就是类型推论。
如果定义的时候没有赋值,不管之后有没有赋值,都会被推断成 any 类型而完全不被类型检查:
let myFavoriteNumber;
myFavoriteNumber = 'seven';
myFavoriteNumber = 7;
交叉类型是将多个类型合并为一个类型。
索引类型查询操作符keyof
interface Person {
name:string;
age:number;
}
let personProps:keyof Person; // personProps的类型就是Person内的键值 "name" | "age"
联合类型(Union Types)表示取值可以为多种类型中的一种。
let myFavoriteNumber: string | number;
myFavoriteNumber = 'seven';
myFavoriteNumber = 7;
联合类型使用 |
分隔每个类型。
当 TypeScript 不确定一个联合类型的变量到底是哪个类型的时候,我们只能访问此联合类型的所有类型里共有的属性或方法:
function getLength(something: string | number): number {
return something.length;
}
// error TS2339: Property 'length' does not exist on type 'string | number'. Property 'length' does not exist on type 'number'.
上例中,length
不是 string
和 number
的共有属性,所以编译器报错。
访问 string
和 number
的共有属性是没问题的:
function getString(something: string | number): string {
return something.toString();
}
联合类型的变量在被赋值的时候,会根据类型推论的规则推断出一个类型:
let myFavoriteNumber: string | number;
myFavoriteNumber = 'seven';
console.log(myFavoriteNumber.length);
myFavoriteNumber = 7;
console.log(myFavoriteNumber.length); // error TS2339: Property 'length' does not exist on type 'number'.
在上例中,第 2 行 myFavoriteNumber
被推断成 string
类型,因此访问其 length
属性不会报错。而第 4 行被推断成 number
,访问 length
就报错了。
类型断言(Type Assertion)可以用来手动指定一个值的类型。
value
// or
value as type
在 tsx
中必须使用后面一种。
前面在联合类型中我们提到过,当 Typescript 不确定一个联合类型的变量到底是哪个类型的时候,我们只能访问此联合类型的所有类型里共有的属性或方法:
function getLength(something: string | number): number {
return something.length;
}
// error TS2339: Property 'length' does not exist on type 'string | number'. Property 'length' does not exist on type 'number'.
而有时候,我们确实需要在还不确定类型的时候就访问其中一个类型的属性或方法,比如:
function getLength(something: string | number): number {
if (something.length) {
return something.length;
} else {
return something.toString().length;
}
}
// error TS2339: Property 'length' does not exist on type 'string | number'. Property 'length' does not exist on type 'number'.
在上例中,访问 something.length
的时候会报错,因为 length
并不是公共属性。此时,我们就可以使用类型断言,将 something
断言成 string
:
function getLength(something: string | number): number {
if ((something).length) {
return (something as string).length;
} else {
return something.toString().length;
}
}
类型断言不是类型转换,断言成一个联合类型中不存在的类型是不允许的:
function toBoolean(something: string | number): boolean {
return something;
}
// error TS2352: Conversion of type 'string | number' to type 'boolean' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first. Type 'number' is not comparable to ty