TypeScript学习笔记(一)

211 阅读6分钟

参考链接:

一、TypeScript安装

使用TypeScript前需要在系统中全局安装TypeScript,使用npm或yarn进行全局安装

npm install typescript -g

yarn global add typescript

由于Node环境不能直接运行.ts文件,需要用tsc xxx.ts将.ts文件转换为Node可运行的.ts文件,操作的效率比较低,所以这里还需安装ts-node插件,使用ts-node就可以直接看到编写结果,使用npm全局安装

npm install -g ts-node

安装完成后,就可以在命令中直接输入如下命令,来查看编译结果了。

ts-node xxx.ts

二、静态类型/基础数据类型

2.1 静态类型

TypeScript 中,使用 : 指定变量的类型,例如,用 : 指定 person、count类型为 string、number

function hello(person: string){

    return 'hello,' + person ;

}

let user = 'lizhien';

console.log(hello(user)); // hello, lizhien 

const count: number = 1;

这里就定义了hello函数和count常量的类型为string和number,使用对应类型上所有的属性和方法。

2.2 自定义静态类型

使用了静态类型,不仅意味着变量的类型不可以改变,还意味着类型的属性和方法也跟着确定了

`interface UserName { `

    name: string, 

    age: number

}

const wen: UserName = { name: 'wenshuaige', age: 18 }

console.log(wen) // { name: 'wenminghao', age: 18 }

2.3 基础数据类型

原始数据类型在 TypeScript 中的应用:

  • 布尔值:

    let isDone: boolean = false;

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

let createdByNewBoolean: Boolean = new Boolean(1);

在 TypeScript 中,boolean 是 JavaScript 中的基本类型,而 Boolean 是 JavaScript 中的构造函数。

  • 数值:

    let count1: number = 6; let count2: number = 0xf11d;// ES6 中的二进制表示法 let binary: number = 0b1010; // ES6 中的八进制表示法 let octalLiteral: number = 0o744; let notANumber: number = NaN; let infinityNumber: number = Infinity;

  • 字符串:

    let myName: string = 'wmh'; let myAge: number = 18; // 模板字符串语法 let userInfo = my name is ${myName},i am ${myAge} years old;

  • 空值:

    function alertName(): void { alert('My name is Tom'); } let unusable: void = undefined;

JavaScript 没有空值(Void)的概念,在 TypeScript 中,可以用 void 表示没有任何返回值的函数,声明一个 void 类型的变量,赋值为undefinednull

  • Null和undefined

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

// 这样不会报错
let count: number = undefined;
let m: undefined;
let newM: number = m;

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

let count: void;
let newM: number = count;
// Type 'void' is not assignable to type 'number'.

2.4 对象类型

  • 对象类型

    const myInfo: { name: string, age: number, } = { name: "wen帅哥", age: 18, }; console.log(myInfo.name); // wen帅哥

  • 数组类型

    const arrayInfo: String[] = ["wen", "shuai", "哥"];

  • 类类型

    class Person {} const wen: Person = new Person();

  • 函数类型

    const userName: () => string = () => { return "wenshuai哥"; };

2.5 任意值类型

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

// 任意值赋值允许更改
let anyNumber: any = 'seven';  
anyNumber = 7; √

// 普通类型不允许被更改
let myFavoriteNumber: string = 'seven'; 
myFavoriteNumber = 7; X

在任意值上访问任何属性都是允许的,也允许调用任何方法:

let anyUser: any = 'wmh';
console.log(anyUser.myName);

anyUser.setName('Tom');

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

let something;
something = 'wmh';
something = 18;

something.setName('Tom');

2.6 类型推论

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

let count = 110;
count  = '110';

// hello.ts:42:1 - error TS2322: Type 'string' is not assignable to type 'number'.

2.7 联合类型

表示取值可以为多种类型中的一种,联合类型使用 | 分隔每个类型

let myFavoriteMovie: string | number; 
myFavoriteMovie= 'xijuzhiwang';
myFavoriteMovie= 007;

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

function getLength(something: string | number): number {
    return something.length;
} 
// hello.ts:45:22 - error TS2339: Property 'length' does not exist on type 'string | number'.
Property 'length' does not exist on type 'number'.
// 此时访问不到length属性

function getString(something: string | number): string {
    return something.toString();
}
//  string和number共有toString()方法可以获取到

联合类型的变量在被赋值的时候,会根据类型推论的规则推断出一个类型:

let myName: string | number;
myName= 'wmh';
console.log(myName.length); // 3myName= 7;
console.log(myName.length); // 编译时报错

// hello.ts:51:20 - error TS2339: Property 'length' does not exist on type 'number'.

三、对象/数组/函数类型

  • 对象的类型——Interfaces

    interface userInfo{ name: string; age: number; }

    let user: userInfo = { name: 'wen', age: 18 };

定义的变量比接口少了一些属性,多一些属性都是不允许的。

有时我们希望定义的变量和接不要完全匹配,那么可以用可选属性

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

let user: Person = {
    name: 'wen'
};

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

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

let user: userInfo= {    name: 'wen',
    gender: 'male'
};

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

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

let tom: userInfo= {    name: 'wen',
    age: 18,
    gender: 'male'
};

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

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

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

let user: UserInfo= {    name: 'wen',
    age: 18,
    gender: 'male'
};

有时候我们希望对象中的一些字段只能在创建的时候被赋值,那么可以用 readonly 定义只读属性:

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

let user: UserInfo= {    id: 110,
    name: 'wen',
    gender: 'male'
};

tom.id = 120;

// hello.ts:65:7 - error TS2540: Cannot assign to 'id' because it is a read-only property.
  • 数组的类型
  1. 最简单的方法是使用「类型 + 方括号」来表示数组:

    const numberArr: number[] = [1, 2, 3]; const stringArr: string[] = ["a", "b", "c"]; const undefinedArr: undefined[] = [undefined, undefined];

    // 如果数组中有多种类型,比如既有数字类型,又有字符串的时候,采用联合类型的声明方式 const arr: (number | string)[] = [1, "string", 2];

  2.接口也可以用来描述数组:

interface NumberArray {
    [index: number]: number;
}
let fibonacci: NumberArray = [1, 1, 2, 3, 5];

  3.数组中对象类型的定义

const userInfoList: { name: string, age: Number }[] = [
  { name: "wen", age: 18 },
  { name: "pengyuyan", age: 28 },
];
// TypeScript 为我们准备了一个概念,叫做类型别名

type ShuaiGe = { name: string, age: Number };
const userInfoList: ShuaiGe[] = [  { name: "wen", age: 18 },
  { name: "pengyuyan", age: 28 },
];
  • 函数的类型

一个函数有输入和输出,要在 TypeScript 中对其进行约束,需要把输入和输出都考虑到:

function total(x: number, y: number): number {
    return x + y;
}
// 输入的参数不能多也不能少
total(1)
total(1,2,3)

在 TypeScript 的类型定义中,=> 用来表示函数的定义,左边是输入类型,需要用括号括起来,右边是输出类型。

let total: (x: number, y: number) => number = function (x: number, y: number): number {
    return x + y;
};

我们也可以使用接口的方式来定义一个函数需要符合的形状:

interface isDone{
    (name: string, title: string): boolean;
}

let mySubject: isDone;mySubject= function(name: string, title: string) {
    return name.search(title) !== -1;
}

我们用 ? 表示可选的参数:

function myName(xing: string, ming?: string) {
    if (ming) {
        return xing+ ' ' + ming;
    } else {
        return xing;
    }
}
let wenMing = buildName('wen', 'Ming');
let wen = buildName('wen');

注:可选参数后面不允许再出现必需参数了。

在 ES6 中,我们允许给函数的参数添加默认值,TypeScript 会将添加了默认值的参数识别为可选参数:

function myName(xing: string, ming: string='ming') {
    if (ming) {        
        return xing+ ' ' + ming;
    } else {
        return xing;
    }
}
let wenMing = buildName('wen', 'Ming');
let wen = buildName('wen');