原始数据类型
JavaScript 的类型分为两种:原始数据类型 和对象类型。
这里要提一下,原始数据类型新增了个 ES6 中的新类型 Symbol
和 ES10 中的新类型 BigInt
。
布尔值
在 TypeScript 中,使用 boolean
定义布尔值类型:
let isDone:boolean = false;
注意使用构造函数 Boolean
创造的对象不是布尔值,返回的是一个对象
let createdByNewBoolean: Boolean = new Boole4an(1);
在 TypeScript 中, boolean 是JavaScript 中的基本类型,二Boolean
是JavaScript 中的构造函数。其他基本类型(除了 null
和 undefined
)一样,不在赘述。
数值
使用 number 定义数值类型:
let myName: string = 'Tom';
let myAge: number = 25;
//模板字符串
let sentence: string = `Hello,my name is ${myName}.
I'll be ${myAge + 1} years old next month.`;
其中 ´
用来定义 ES6 中的模板字符串, ${expr}
用来在模板字符换种嵌入表达式。
空值
JavaScript 中没用空值(void)的概念,在 Typescript 中, 可以用 void 表示没有任何放回值的函数:
function alertName(): void {
alert('My name is Jone');
}
Null 和 Undefined
在 TypeScript 中,可以使用 null
和 undefined
来定义这两个原始数据类型:
let u: undefined = undefined;
let n:null = null;
与 void
的区别是, undefined
和 null
是所有类型的子类型。也就是说 undefined
类型的变量,可以赋值给 number
类型的变量:
let u: undefined;
let num: number = u;
而 void
类型的变量不能赋值给 number
类型的变量
任意值
任意值(Any)用来表示允许赋值为任意类型。
什么是任意值类型
如果是一个普通类型,在赋值过程中改变类型是不被允许的:
let myFavoriteNumber: string = 'seven';
myFavoriteNumber =7
//Type 'number' is not assignable to type 'string'.
我们可以看到这边编译时报错,提示我们 number
类型无法分配给类型 string
,那么当我们使用 any
类型:
let myFavoriteNumber: any = 'seven';
myFavoriteNumber =7
任意值的属性和方法
在任意值上访问任何属性嗲用任何方法都是可以的
let anyThing: any = 'hello';
console.log(anyThing.myName);
console.log(anyThing.myName.firstName);
let anyThing: any = 'Tom';
anyThing.setName('Jerry');
anyThing.setName('Jerry').sayHello();
anyThing.myName.setFirstName('Cat');
从上代码可观察到,声明一个变量为任意值之后,对它的任何操作,返回的内容的类型都是任意值。
未声明类型的变量
变量如果在生命的时候,未指定气类型,那么它就会被识别为任意值类型:
let something;
something = 'seven';
something = 7;
something.setName('Tom');
类型推论
如果没有明确的指定类型,那么 TypeScript 会依照类型推论的规则推断出一个类型。
什么是类型推论
以下代码虽然没有指定类型,但是会在编译的时候报错:
let myFavoriteNumber = 'seven';
myFavoriteNumber = 7;
//Type 'number' is not assignable to type 'string'.
TypeScript 会在没有明确的指定类型的时候推测出一个类型,这就是类型推论,但是如果定义的时候没赋值,不管之后有没有赋值,都会被推断成 any
类型而完全不被类型检查:
let myFavoriteNumber;
myFavoriteNumber = 'seven';
myFavoriteNumber = 7;
联合类型
联合类型表示取值可以为多种类型中的一种。
let myFavoriteNumber: string | number;
myFavoriteNumber = 'seven';
myFavoriteNumber = 7;
联合类型使用 |
分隔每个类型。
上述代码,允许 myFavoriteNumber
的类型是 string
或者 number
,但是不能是其他类型。联合类型的变量在被赋值的时候,会根据类型推论的规则推断出一个类型:
let myFavoriteNumber: string | number;
myFavoriteNumber = 'seven';
console.log(myFavoriteNumber.length); // 5
myFavoriteNumber = 7;
console.log(myFavoriteNumber.length); // 编译时报错
// Property 'length' does not exist on type 'number'.
上述例子, myFavoriteNumber
被推断成了 string
,访问它的 length
属性不会报错。而后 myFavoriteNumber
被推断成了 number
,访问它的 length
属性时就报错了。
对象的类型——接口
在 TypeScript 中,我们使用接口来定义对象的类型。
什么是接口
在面向对象语言中,接口是一个很重要的概念,它是对行为的抽象,而具体如何行动需要由类去实现。
下面我们通过一个简单的例子来看看:
interface Person{
name: string;
age: number;
}
let tom: Person = {
name: 'Tom',
age: 25
};
上述例子中,我们定义了一个接口 Person
, 接着定义了个变量 tom
,它的类型是 Person
。这样我们就约束了 tom
的形状必须和接口 Person
一致。
接口一般首字母大写。定义的变量比接口无论多或者少了一些属性是不被允许的。
可选属性
当我们希望不要完全匹配一个形状,那么可以用可选属性。
interface Person {
name: string;
age?: number;
}
let tom: Person = {
name: 'Tom'
};
可选属性的含义是该属性可以不存在,这是仍然不允许添加未定义的属性。
任意属性
当我们希望一个接口允许有任意的属性,可以使用如下方式:
interface Person{
name: string;
age?: number;
[propName: string]:any;
}
let tom: Person ={
name: 'Tom',
gender: 'male'
};
上述例子设置了个可选属性 age
,并且使用 [propName: string]
定义了任意属性取 string
类型的值。
这有个需要注意的点:一旦定义了任意属性,那么确定属性和可选属性的类型都必须是它的类型子集,并且一个接口只能定义一个任意属性,如果接口中有多个类型的属性,则可以在任意属性中使用联合类型。
interface Person{
name: string;
age?: number;
[propName:string]: string | number;
}
let tom: Person = {
name: 'Tom',
age: 25,
gender: 'male'
};
只读属性
当我们希望对象中的一些字段只能在创建的时候被复制,那么可以用 readonly
定义只读属性:
interface Person {
readonly id: number;
name: string;
age?: number;
[propName: string]: any;
}
let tom: Person = {
id: 89757,
name: 'Tom',
gender: 'male'
};
tom.id = 9527;
上述例子,使用 readonly
定义的属性 id
初始化后,又被赋值了,所以报错了。
注意,只读的约束存在于第一次给对象赋值的时候,而不是第一次给只读属性赋值的时候。