TypeScript 基础

177 阅读5分钟

原始数据类型

JavaScript 的类型分为两种:原始数据类型 和对象类型。

这里要提一下,原始数据类型新增了个 ES6 中的新类型 Symbol 和 ES10 中的新类型 BigInt

布尔值

在 TypeScript 中,使用 boolean 定义布尔值类型:

let isDone:boolean = false;

注意使用构造函数 Boolean 创造的对象不是布尔值,返回的是一个对象

let createdByNewBoolean: Boolean = new Boole4an(1); 

在 TypeScript 中, boolean 是JavaScript 中的基本类型,二Boolean 是JavaScript 中的构造函数。其他基本类型(除了 nullundefined)一样,不在赘述。

数值

使用 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 中,可以使用 nullundefined 来定义这两个原始数据类型:

let u: undefined = undefined;
let n:null = null;

void 的区别是, undefinednull 是所有类型的子类型。也就是说 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 初始化后,又被赋值了,所以报错了。 注意,只读的约束存在于第一次给对象赋值的时候,而不是第一次给只读属性赋值的时候。

原文 《TypeScript 入门教程》