TS学习(一)

140 阅读5分钟

官方playground

官方也提供了一个在线开发 TypeScript 的云环境——Playground 英文版 中文版

基于它,我们无须在本地安装环境,只需要一个浏览器即可随时学习和编写 TypeScript,同时还可以方便地选择 TypeScript 版本、配置 tsconfig,并对 TypeScript 实时静态类型检测、转译输出 JavaScript 和在线执行。检查语法故障和检查逻辑故障。

一.基元类型

JavaScript 的类型分为两种:原始数据类型(Primitive data types)和对象类型(Object types)。

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

1.基元类型(string,number,boolean)

const str:string = '';
const num:number = 0;
const bol:boolean = true;

2.数组(array)

  1. 「类型 + 方括号」表示
  2. 数组泛型(Array Generic) [Array<elemType>] 表示
  3. 用接口表示
  4. any表示数组中允许出现任意类型
const arr:number[] = [1,2,3];
const arr2:Array<number> = [1,2,3];
interface NumberArray {
    [index: number]: number;
}
let arr3: NumberArray = [1, 1, 2, 3, 5];
let list: any[] = ['xcatliu', 25, { website: 'http://xcatliu.com' }];

3.any(不希望某个特定值导致类型检查错误)

允许被赋值为任意类型

声明一个变量为任意值之后,对它的任何操作,返回的内容的类型都是任意值。

let myFavoriteNumber: any = 'seven';
myFavoriteNumber = 7;

4.变量上的类型注释

let str='';
str = 其他类型时报错

5.函数

在 JavaScript 中,有两种常见的定义函数的方式—— 函数声明 和 函数表达式

// 1.函数声明(Function Declaration)
function sum(x, y) {
    return x + y;
}
// TS
function sum(x: number, y: number): number {
    return x + y;
}


// 2.函数表达式(Function Expression)
let mySum = function (x, y) {
    return x + y;
};
// TS
let mySum = function (x: number, y: number): number {
    return x + y;
};
// TS优化版
// 在 TypeScript 的类型定义中,`=>` 用来表示函数的定义,左边是输入类型,需要用括号括起来,右边是输出类型
let mySum: (x: number, y: number) => number = function (x: number, y: number): number {
    return x + y;
};

用接口定义函数的形状

interface SearchFunc {
    (source: string, subString: string): boolean;
}

let mySearch: SearchFunc;
mySearch = function(source: string, subString: string) {
    return source.search(subString) !== -1;
}

可选参数, 可选参数后面不允许再出现必需参数了

参数默认值, 没有可选参数必须接在必需参数后面」的限制了

function buildName(firstName: string = 'Tom', lastName: string) {
    return firstName + ' ' + lastName;
}
buildName(undefined, 'Cat')

剩余参数

function push(array, ...items) {
    items.forEach(function(item) {
        array.push(item);
    });
}

let a: any[] = [];
push(a, 1, 2, 3);

重载

重载允许一个函数接受不同数量或类型的参数时,作出不同的处理

function reverse(x: number | string): number | string | void {
    if (typeof x === 'number') {
        return Number(x.toString().split('').reverse().join(''));
    } else if (typeof x === 'string') {
        return x.split('').reverse().join('');
    }
}

参数类型注释(:string)/返回值类型注释(:void)

void 表示没有任何返回值的函数

类型推论: 根据输入值判断值是什么类型

function fun(name:string):void{
    console.log(name)
}

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

6.对象类型

function fun2(obj: {x:string,y:string}):void{
    console.log(obj.x, obj.y)
    console.log(obj.x.toUpperCase())
}
fun2({x:1,y:2})

7.联合类型(两个或多个类型组成)

// 表示取值可以为多种类型中的一种
let myFavoriteNumber: string | number;
myFavoriteNumber = 'seven';
myFavoriteNumber = 7;
myFavoriteNumber = true; //报错

// 访问此联合类型的所有类型里共有的属性或方法
function getLength(something: string | number): number {
    return something.length; //报错,length不是number的方法
}

function getString(something: string | number): string {
    return something.toString();
}

8.类型别名(首字母大写)

type Point = {
    x: number;
    y: number;
}
type ID = number | string;
type Str = string;
function fun(id: ID):void{
    console.log(id)
}

type Large = Point & {
    z: number;
}
const large: Large = {
    x: 1,
    y: 2,
    z: 3
}

//type创建后不能更改

9.接口(首字母大写)

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

赋值的时候,变量的形状必须和接口的形状保持一致, 不允许添加未定义的属性


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

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

//可选属性
interface Person {
    name: string;
    age?: number;
}

let tom: Person = {
    name: 'Tom'
};

// 任意属性
interface Person {
    name: string;
    age?: number;
    [propName: string]: any;
}
// 如果任意属性定义为string, age的number会报错,所以应修改为联合类型
interface Person {
    name: string;
    age?: number;
    [propName: string]: string | number;
}
// 只读属性
interface Person {
    readonly id: number;
    name: string;
    age?: number;
    [propName: string]: any;
}


interface Large extends Point: {
    z: number;
}
const large: Large = {
    x: 1,
    y: 2,
    z: 3
}

//向现有的类型添加字段
interface Lists: {
    x: number;
}
interface Lists: {
    y: number;
}
const list: Lists = {
    x: 1,
    y: 2,
}

10.类型断言

值 as 类型 或 <类型>值

interface Cat {
    name: string;
    run(): void;
}
interface Fish {
    name: string;
    swim(): void;
}

function swim(animal: Cat | Fish) {
    (animal as Fish).swim();
    // 一旦传入的参数是 `Cat` 类型的变量,由于 `Cat` 上没有 `swim` 方法,就会导致运行时错误了
}

### 将一个父类断言为更加具体的子类
class ApiError extends Error {
    code: number = 0;
}
class HttpError extends Error {
    statusCode: number = 200;
}

function isApiError(error: Error) {
    if (error instanceof ApiError) {
        return true;
    }
    return false;
}

// 返回某种类型的HTMLElement
const clas = document.getElementById('main_canvas') as HTMLCanvasElement
const clas = <HTMLCanvasElement>document.getElementById('main_canvas')

const x = ('hello' as any) as number
const x = ('hello' as unknow) as number

11.文字类型

// let声明后可修改, const 声明后不可修改
function compare(a:string, b:string): -1|0|1 {
    return a === b ? 0: a > b ? 1: -1
}

const  obj= {
    x: 1
}
obj.x=2
obj.y =3 // Property 'y' does not exist on type '{ x: number; }'


const  arr= [1,2,3,4]
arr.push(5)

12.null和undefined类型

// null不存在 undefined未初始化的值
let x:null = null
let y:undefined = undefined

function live(x?: number | null) {
    console.log(x!.toFixed(2))
}
// 1. 属性或参数中使用 ?:表示该属性或参数为可选项
// 2. 属性或参数中使用 !:表示强制解析(告诉编译器,这里一定有值),常用于vue-decorator中的@Prop
// 3. 变量后使用 !:表示类型推断排除null、undefined

13.枚举

enum Point: {
    Up = 1,
    Down,
}

14.bigint和symbol

//bigint非常大的整数 symbol全局唯一引用
const num: bigint = BigInt(100)

15.内置对象

ECMAScript 标准提供的内置对象有:

BooleanErrorDateRegExp 等。

我们可以在 TypeScript 中将变量定义为这些类型:

let b: Boolean = new Boolean(1);
let e: Error = new Error('Error occurred');
let d: Date = new Date();
let r: RegExp = /[a-z]/;

DOM 和 BOM 提供的内置对象有:

DocumentHTMLElementEventNodeList 等。

TypeScript 中会经常用到这些类型:

let body: HTMLElement = document.body;
let allDiv: NodeList = document.querySelectorAll('div');
document.addEventListener('click', function(e: MouseEvent) {
  // Do something
});