typescript基础知识总结


前言

一、什么是TypeScript?

TypeScript 是添加了类型系统的 JavaScript,适用于任何规模的项目。
TypeScript 是一门静态类型、弱类型的语言。
TypeScript 是完全兼容 JavaScript 的,它不会修改 JavaScript 运行时的特性。
TypeScript 可以编译为 JavaScript,然后运行在浏览器、Node.js 等任何能运行 JavaScript 的环境中。
TypeScript 拥有很多编译选项,类型检查的严格程度由你决定。
TypeScript 可以和 JavaScript 共存,这意味着 JavaScript 项目能够渐进式的迁移到 TypeScript。
TypeScript 增强了编辑器(IDE)的功能,提供了代码补全、接口提示、跳转到定义、代码重构等能力。
TypeScript 拥有活跃的社区,大多数常用的第三方库都提供了类型声明。
TypeScript 与标准同步发展,符合最新的 ECMAScript 标准(stage 3)。

二、安装TypeScript

1.TypeScript 的命令行工具安装方法如下:

	npm install -g typescript

2.运行TypeScript文件

	用命令行  tsc XXX.ts

三、基础知识

1、原始数据类型

	原始数据类型包括:布尔值、数值、字符串、null、undefined 以及 ES6 中的新类型 Symbol 和 ES10 中的新类型 BigInt。

布尔值

布尔值是最基础的数据类型,在 TypeScript 中,使用 boolean 定义布尔值类型:

let isDone: boolean = false;
// 编译通过
// 后面约定,未强调编译错误的代码片段,默认为编译通过

注意,使用构造函数 Boolean 创造的对象不是布尔值:

let createdByNewBoolean: boolean = new Boolean(1);

// Type 'Boolean' is not assignable to type 'boolean'.
//   'boolean' is a primitive, but 'Boolean' is a wrapper object. Prefer using 'boolean' when possible.

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

数值

使用 number 定义数值类型:

let a: number = 6;
let b: number = NaN;
let c: number = Infinity;

编译结果:

var a = 6;
var b = NaN;
var c = Infinity;

字符串

使用 string 定义字符串类型:

let myName: string = 'tom';
let myAge: number = 23;
// 模板字符串
let sentence: string = `my name is ${myName}.I${myAge + 1} years. `;

编译结果

var myName = 'Tom';
var myAge = 23;
// 模板字符串
var sentence = "my name is" + myName + ".\nI" + myAge + " years.";

空值

JavaScript 没有空值(Void)的概念,在 TypeScript 中,可以用 void表示没有任何返回值的函数:

function alertName(): void {
    alert('My name is Tom');
}

声明一个void类型的变量没有什么用,因为你只能将它赋值为 undefined 和 null(只在strictNullChecks 未指定时):

let unusable: void = undefined;
let unnull: void = null;

Null 和 Undefined

在 TypeScript 中,可以使用 null 和 undefined 来定义这两个原始数据类型:

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

void的区别是,undefined和null可以赋值给所有类型,比如number、string、布尔值

let num : number = undefined;
let s : string = undefined;
let b : boolean = undefined;

编译结果

var num = undefined;
var s = undefined;
var b = undefined;

而 void 类型的变量不能赋值给 number 类型的变量:

let v : void;

let num : number = v;
// Type 'void' is not assignable to type 'number'.

2、任意值

任意值(Any)用来表示允许赋值为任意类型。

普通类型是不允许被改变类型。

let ordinaryStr : string = '8';
ordinaryNum = 8;
//Type 'number' is not assignable to type 'string'.

如果是 any 类型,则允许被赋值为任意类型。

let anyStr : any = '8';
	anyStr = 8;

在被设置为任意值的变量上 ,访问该变量中任何属性和调用方法都是允许的。

未声明类型的变量

变量如果在声明的时候,未指定其类型,那么它会被识别为任意值类型:

let anything;
	anything = '8';
	anything = 8;
	anything.setName('eight');

等价于

let anything : any;
	anything = '8';
	anything = 8;
	anything.setName('eight');

3、类型推论

如果没有明确的指定类型,那么 TypeScript 会依照类型推论(Type Inference)的规则推断出一个类型。

1、一种是定义变量且赋值:

let myNum = 8;
	myNum = '8';
// Type 'string' is not assignable to type 'number'.

等价于

let myNum : number = 8;
	myNum = '8';
// Type 'string' is not assignable to type 'number'

2、另一种是定义变量且没有赋值:

let myNum;
	myNum = '8';
	myNum = 8;

如果定义的时候没有赋值,不管之后有没有赋值,都会被推断成 any 类型而完全不被类型检查。

4、联合类型

联合类型(Union Types)表示取值可以为多种类型中的一种。

1、例子:

let myNum : string | number;
	myNum = '8';
	myNum = 8;
let myNum : string | number;
	myNum = true;
//  Type 'boolean' is not assignable to type 'string | number'

这里的 let myNum : string | number 的含义是,允许 myNum 的类型是 string 或者 number,但是不能是其他类型。

2、访问联合类型的属性或方法:

当 TypeScript 不确定一个联合类型的变量到底是哪个类型的时候,我们只能访问此联合类型的所有类型里共有的属性或方法:

function getLength(something: string | number): number {
    return something.length;
}
// 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 myNum : string | number;
	myNum = 'eight' ;
	console.log(myNum.length); // 5
	myNum = 7;
	console.log(myNum .length); // 编译时报错,Property 'length' does not exist on type 'number'. 

上例中,第二行的 myNum 被推断成了 string,访问它的 length 属性不会报错。

而第四行的 myNum 被推断成了 number,访问它的 length 属性时就报错了。

5、对象的类型——接口

1、什么是接口

在面向对象语言中,接口(Interfaces)是一个很重要的概念,它是对行为的抽象,而具体如何行动需要由类(classes)去实现(implement)。

TypeScript 中的接口是一个非常灵活的概念,除了可用于对类的一部分行为进行抽象以外,也常用于对「对象的形状(Shape)」进行描述。

2、例子:

interface Person {
    name : string,
    age : number
}
let tom: Person = {
    name : 'tom',
    age : 18
}

上面的例子中,我们定义了一个接口 Person,接着定义了一个变量 tom,它的类型是 Person。这样,我们就约束了 tom 的形状必须和接口 Person 一致。

接口一般首字母大写。有的编程语言中会建议接口的名称加上 I 前缀。

定义的变量比接口少了一些属性是不允许的:

interface Person {
    name : string,
    age : number
}
let tom: Person = {
    name : 'tom',
}
// Property 'age' is missing in type '{ name: string; }' but required in type 'Person'.

多一些属性也是不允许的:

interface Person {
    name : string,
    age : number
}
let tom: Person = {
     name : 'Tom',
     age : 25,
     gender : 'male'
}
// test.ts(8,6): error TS2322: Type '{ name: string; age: number; gender: string; }' is not assignable to type 'Person'.
// Object literal may only specify known properties, and 'gender' does not exist in type 'Person'.

3、可选属性

有时我们希望不要完全匹配一个形状,那么可以用可选属性:

interface Person {
    name: string;
    age?: number;
}

let tom: Person = {
    name: 'Tom'
};
interface Person {
    name: string;
    age?: number;
}

let tom: Person = {
    name: 'Tom',
    age: 25
};

可选属性的含义是该属性可以不存在。

这时仍然不允许添加未定义的属性

interface Person {
    name: string;
    age?: number;
}

let tom: Person = {
    name: 'Tom',
    age: 25,
    gender: 'male'
};
// test.ts(9,5): error TS2322: Type '{ name: string; age: number; gender: string; }' is not assignable to type 'Person'.
// Object literal may only specify known properties, and 'gender' does not exist in type 'Person'.

4、任意属性

有时候我们希望一个接口允许有任意的属性,可以使用如下方式:

interface Person {
    name: string;
    age?: number;
    [propName: string]: any;
}

let tom: Person = {
    name: 'Tom',
    gender: 'male'
};

使用 [propName: string] 定义了任意属性取 string 类型的值。
使用 [propName: string]: any;定义了任意属性可以取任何类型的值。

需要注意的是,一旦定义了任意属性,那么确定属性和可选属性的类型都必须是它的类型的子集

interface Person {
    name: string;
    age?: number;
    [propName: string]: string;
}

let tom: Person = {
    name: 'Tom',
    age: 25,
    gender: 'male'
};
// test.ts(3,5): error TS2411: Property 'age' of type 'number' is not assignable to string index type 'string'.
// test.ts(7,5): error TS2322: Type '{ name: string; age: number; gender: string; }' is not assignable to type 'Person'.
// Property 'age' is incompatible with index signature.
// Type 'number' is not assignable to type 'string'.

上例中,任意属性的值允许是 string,但是可选属性 age 的值却是 number,number 不是 string 的子属性,所以报错了。

另外,在报错信息中可以看出,此时{ name: 'Tom', age: 25, gender: 'male' }的类型被推断成了{ [x: string]: string | number; name: string; age: number; gender: string; },这是联合类型和接口的结合。

一个接口中只能定义一个任意属性。如果接口中有多个类型的属性,则可以在任意属性中使用联合类型:

interface Person {
    name: string;
    age?: number;
    [propName: string]: string | number; //  [propName: string]: any; 定义任意类型
}

let tom: Person = {
    name: 'Tom',
    age: 25,
    gender: 'male'
};

5、只读属性

有时候我们希望对象中的一些字段只能在创建的时候被赋值,那么可以用 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;
// test.ts(14,5): error TS2540: Cannot assign to 'id' because it is a read-only property.

上例中,使用 readonly 定义的属性 id 初始化后,又被赋值了,所以报错了。

注意,只读的约束存在于第一次给对象赋值的时候,而不是第一次给只读属性赋值的时候:

interface Person {
    readonly id: number;
    name: string;
    age?: number;
    [propName: string]: any;
}

let tom: Person = {
    name: 'Tom',
    gender: 'male'
};

tom.id = 89757;
// test.ts(8,5): error TS2741: Property 'id' is missing in type '{ name: string; gender: string; }' but required in type 'Person'.
// test.ts(13,5): error TS2540: Cannot assign to 'id' because it is a read-only property.

上例中,报错信息有两处,第一处是在对 tom 进行赋值的时候,没有给 id 赋值。

第二处是在给 tom.id 赋值的时候,由于它是只读属性,所以报错了。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值