TypeScript教程之二:类型


基本类型定义

顾名思义,静态类型变量一旦声明,不可改变其类型。比如:如下代码就会报错:

TypeScript
let firstName: string = 'ls';
firstName = 12

上面代码中的 let firstName : string 其实就是一种类型注解(type annotation)。之所以叫做静态类型,是因为TS中的类型并不是在运行时起作用的,而是在编译成JS之前进行的检查,因此仅仅是静态类型,而非运行时的动态检查。如果检查编译后的JS,就会发现,在编译后的JS中,原来在TS中声明的变量类型都不复存在了

其实,TS还能进行类型推断(type inference),比如,在下面代码中,一旦给变量c赋值12,TS就能推断出其类型为number:

TypeScript
let c = 12;

因此,在TS中,如果能够推断类型,可以不用进行类型注解,否则,必须明确声明类型

TypeScript的七种基本类型包括:

  • string
  • number
  • boolean
  • bigint
  • symbol
  • null
  • undefined

类型别名Type Alias

可以为类型指定一个别名,之后通过这个别名来声明类型:

TypeScript
type StringOrNum = string | number;
type ObjWithName = {name: string, uid: StringOrNum}

定义对象类型

除了使用基本类型外,也可以使用自定义类型来定义一个静态变量。

直接定义

这种方式相当是定义了一个匿名类型,然后直接使用:

TypeScript
let jessie: {
    id: string,
    name: string,
    age: number
} = {
    id: '9901',
    name: 'Jessie',
    age: 25
}

console.log(jessie);

使用接口来定义

TypeScript
interface IStudent {
    id: string,
    name: string,
    age: number
}

function registerStudent(s: IStudent) {
    console.log(s);
}

const jessie : IStudent = {
    id: '9901',
    name: 'Jessie',
    age: 25
}

registerStudent(jessie);

运行这段代码的输出为:

bash
{ id: '9901', name: 'Jessie', age: 25 }

使用类型定义数组

TypeScript
let oddNumbers : number[] = [1, 3, 5, 7, 9];
let studentNames: string[] = ['Jessie', 'Lucas'];
let undefinedArr: undefined[] = [undefined, undefined];
let mixedArr: (number | string)[] = ['Jessie', 123];

let studentObjects: {name:string, age:number}[] = [
    {name: 'Jessie', age: 22},
    {name: 'Lucas', age: 21}
]

对于混合型的数组,TS可以进行类型推断,比如,如下定义也是合法的:

TypeScript
let mixed = ['George', 25, 30, 'Paul'];

也可以把对类型的定义抽象出来,单独定义个类型,便于以后重用:

TypeScript
type Student = {
    name: string,
    age: number
};

let studentObjects2 : Student[] = [
    {name: 'Jessie', age: 22},
    {name: 'Lucas', age: 21}
]

当然,也可以单独定义一个类:

TypeScript
class Teacher {
    name: string = 'Nobody';
    subject: string = 'Math';
}

let teachers: Teacher[] = [
    {name: 'Paul', subject: 'Math'},
    {name: 'Jim', subject: 'Computing'}
]

使用元组

尽管可以使用类似这样的类型定义混合元素的数组:

TypeScript
let mixedArr: (number | string)[] = ['Jessie', 'Math', 28];

但由于它对其中元素只约束了可能的类型,但并未约束顺序,因此,有可能在赋值时出现逻辑错误,比如:

TypeScript
let mixedArr: (number | string)[] = ['Jessie', 28, 'Math'];

上面语句语法没错误,因此TS不会报错,但其逻辑上却不对了。本来期待数组中的第二个元素为subject,但这里却可以把subject和age互换。

为了解决这个问题,在TS中可以使用元组来定义数组中元素类型的准确次序

TypeScript
let yearOneTeachers : [string, string, number][] = [
    ['Jessie', 'Math', 28],
    ['Lucy', 'English', 37],
    ['Paul', 'Computing', 55]
]

元组示例:

TypeScript
class StudentHelper {
    static register(id: number, name: string, address: string) {
    }
}

let values: [number, string, string];
values = [1, 'Lucy', '1 Fake Street'];
StudentHelper.register(...values);

xx.d.ts是什么东东?

在使用TS的时候,经常会看到类似xx.d.ts的文件,那么这种文件的作用又是什么呢?

先来看一个问题,如果我们打算使用一个旧版本的JS库,比如jQuery:

TypeScript
$(function() {
    console.log("demo");
});

这时,在VS Code中会在 $ 下面标红,并提示:

bash
Cannot find name '$'. Do you need to install type definitions for jQuery? Try `npm i --save-dev @types/jquery`.ts(2581)

当然,此时可以通过三种方式来解决这个问题:

安装对应的类型声明

bash
npm i -D @types/jquery

骗过TS编译器

或者,在顶部声明:

TypeScript
declare var $: any;

创建xx.d.ts文件

对于常用的JS库,比如jQuery,都有现成的类型声明,只需按照第一种方法安装即可。但对于不常见的第三方库,或自己项目中的传统JS库,就需要创建一个xx.d.ts文件,并在该文件中声明对应的类型。

这时,首先需要更新tsconfig.json文件:

json
"baseUrl": ".",
"paths": {"./node_modules/@types", "./typings/*"},   

接下来创建和第三方模块同名的文件夹,并创建文件xx.d.ts:

bash
mkdir lscoding
touch lscoding/lscoding.d.ts

lscoding.d.ts的内容类似于:

TypeScript
declare function f1(a: number, b: string): number
export = f1

自动创建xx.d.ts的工具

访问:https://www.typescriptlang.org/play


文章作者: 逻思
版权声明: 本博客所有文章除特別声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 逻思 !