Typescript 技术点总结

Typescript 技术点总结

1、原始数据类型

布尔值 boolean

let isDone: boolean = false;
//或者构造函数类型
let createdByNewBoolean: Boolean = new Boolean(1);
//或者通过下面方式返回布尔类型
let createdByBoolean: boolean = Boolean(1);

数值 number

let decLiteral: number = 6;
let hexLiteral: number = 0xf00d;
// ES6 中的二进制表示法
let binaryLiteral: number = 0b1010;
// ES6 中的八进制表示法
let octalLiteral: number = 0o744;
let notANumber: number = NaN;
let infinityNumber: number = Infinity;

字符串 string

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.`;

空值 void

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

function alertName(): void {
    alert('My name is Tom');
}
//声明一个 void 类型的变量没有什么用,因为你只能将它赋值为 undefined 和 null
let unusable: void = undefined;

null 和 undefined

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

与 void 的区别是,undefined 和 null 是所有类型的子类型。也就是说 undefined 类型的变量,可以赋值给 number 类型的变量

// 这样不会报错
let num: number = undefined;
// 这样也不会报错
let u: undefined;
let num: number = u;
//但这样就报错
let u: void;
let num: number = u;
// index.ts(2,5): error TS2322: Type 'void' is not assignable to type 'number'.

任意值 any

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

let myFavoriteNumber: any = 'seven';
myFavoriteNumber = 7;
//声明一个变量为任意值之后,对它的任何操作,返回的内容的类型都是任意值。

联合类型

let myFavoriteNumber: string | number;
myFavoriteNumber = 'seven';
myFavoriteNumber = 7;

联合类型的属性和方法

//只能访问共有的属性或方法
function getString(something: string | number): string {
    return something.toString();
}

2、对象类型

接口 Interfaces

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

let tom: Person = {
    name: 'Tom',
    age: 25
};
//必须一一对应,少属性报错

可选属性

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'
};
let tom1: Person = {
    name: 'Tom',
    age: 25,
    gender: 'male'
};
//tom1报错,age是任意类型的子集,不为字符串

只读属性 readonly

//第一次给对象赋值的时候
interface Person {
    readonly id: number;
    name: string;
    age?: number;
    [propName: string]: any;
}

数组

  • 第一种
let fibonacci: number[] = [1, 1, 2, 5];
  • 第二种:数组泛型
let fibonacci: Array<number> = [1, 1, 2, 5];
  • 第三种:接口表示数组
interface NumberArray {
    [index: number]: number;
}
let fibonacci: NumberArray = [1, 1, 2, 3, 5];
//NumberArray 表示:只要 index 的类型是 number,那么值的类型必须是 number。
  • 第四种:any
let list: any[] = ['Xcat Liu', 25, { website: 'http://xcatliu.com' }];

类数组

扫描二维码关注公众号,回复: 6647275 查看本文章

上常见的类数组都有自己的接口定义,如 IArguments, NodeList, HTMLCollection等:

function sum() {
    let args: IArguments = arguments;
}

函数

函数声明

function sum(x: number, y: number): number {
    return x + y;
}
//执行时多余定义参数或者小于都不被允许

函数表达式

let mySum = function (x: number, y: number): number {
    return x + y;
};
//如果需要我们手动给 mySum 添加类型
let mySum: (x: number, y: number) => number = function (x: number, y: number): number {
    return x + y;
};
//这里的 => 不是es6的 => 

用接口定义函数的形状

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, lastName?: string) {
    if (lastName) {
        return firstName + ' ' + lastName;
    } else {
        return firstName;
    }
}
let tomcat = buildName('Tom', 'Cat');
let tom = buildName('Tom');

可选参数后面不允许再出现必须参数了
参数默认值

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

剩余参数

//只能是最后一个参数
function push(array: any[], ...items: any[]) {
    items.forEach(function(item) {
        array.push(item);
    });
}

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

重载

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

类型断言

需要在还不确定类型的时候就访问其中一个类型的属性或方法,可以使用类型断言

function getLength(something: string | number): number {
    if ((<string>something).length) {
        return (<string>something).length;
    } else {
        return something.toString().length;
    }
}
//类型断言不是类型转换,断言成一个联合类型中不存在的类型是不允许的

声明文件

声明语句

declare var jQuery: (selector: string) => any;

jQuery('#foo');

上例中,declare var 并没有真的定义一个变量,只是定义了全局变量 jQuery的类型,仅仅会用于编译时的检查,在编译结果中会被删除

全局变量声明文件

  • 通常我们会把声明语句放到一个单独的文件(jQuery.d.ts)中,这就是声明文件
  • 声明文件必需以d.ts为后缀。

第三方声明文件

npm install @types/jquery --save-dev

书写声明文件

  • 要是以npm install @types/xxx --save-dev安装的,则不需要配置

declare var

// src/jQuery.d.ts

declare const jQuery: (selector: string) => any;
//使用
jQuery('#foo');

declare function

// src/jQuery.d.ts

declare function jQuery(selector: string): any;
declare function jQuery(domReadyCallback: () => any): any;
//使用
jQuery('#foo');
jQuery(function() {
    alert('Dom Ready!');
});

declare class
declare class语句也 只能用来定义类型,不能用来定义具体的实现 ,比如定义 sayHi方法的具体实现则会报错

// src/Animal.d.ts

declare class Animal {
    name: string;
    constructor(name: string);
    sayHi(): string;
}
//使用
// src/index.ts

let cat = new Animal('Tom');

declare emun
declare emun语句也 只能用来定义类型,不能用来定义具体的值

// src/Directions.d.ts

declare enum Directions {
    Up,
    Down,
    Left,
    Right
}
//使用
// src/index.ts

let directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right];

declare namespace

// src/jQuery.d.ts

declare namespace jQuery {
    function ajax(url: string, settings?: any): void;
}
//使用
// src/index.ts

jQuery.ajax('/api/get_something');

interface 和 type

// src/jQuery.d.ts

interface AjaxSettings {
    method?: 'GET' | 'POST'
    data?: any;
}
declare namespace jQuery {
    function ajax(url: string, settings?: AjaxSettings): void;
}
//使用
// src/index.ts

let settings: AjaxSettings = {
    method: 'POST',
    data: {
        name: 'foo'
    }
};
jQuery.ajax('/api/post_something', settings);

防止命名冲突

// src/jQuery.d.ts
//放到namespace下
declare namespace jQuery {
    interface AjaxSettings {
        method?: 'GET' | 'POST'
        data?: any;
    }
    function ajax(url: string, settings?: AjaxSettings): void;
}
//使用
// src/index.ts

let settings: jQuery.AjaxSettings = {
    method: 'POST',
    data: {
        name: 'foo'
    }
};
jQuery.ajax('/api/post_something', settings);

声明合并

// src/jQuery.d.ts

declare function jQuery(selector: string): any;
declare namespace jQuery {
    function ajax(url: string, settings?: any): void;
}
//使用
// src/index.ts

jQuery('#foo');
jQuery.ajax('/api/get_something');

npm包

  • 判断依据是 package.json 中有 types 字段,或者有一个 index.d.ts 声明文件
  • 尝试安装一下对应的 @types 包就知道是否存在该声明文件,安装命令是 npm install @types/foo --save-dev
  • 创建一个 types目录,专门用来管理自己写的声明文件,将 foo的声明文件放到 types/foo/index.d.ts中。这种方式需要配置下tsconfig.json中的 pathsbaseUrl字段。
目录结构
/path/to/project
├── src
|  └── index.ts
├── types
|  └── foo
|     └── index.d.ts
└── tsconfig.json

tsconfig.json 内容

{
    "compilerOptions": {
        "module": "commonjs",
        "baseUrl": "./",
        "paths": {
            "*": ["types/*"]
        }
    }
}

export导出

// types/foo/index.d.ts

declare const name: string;
declare function getName(): string;
declare class Animal {
    constructor(name: string);
    sayHi(): string;
}
declare enum Directions {
    Up,
    Down,
    Left,
    Right
}
interface Options {
    data: any;
}

export { name, getName, Animal, Directions, Options };
//导入模块
// src/index.ts

import { name, getName, Animal, Directions, Options } from 'foo';

console.log(name);
let myName = getName();
let cat = new Animal('Tom');
let directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right];
let options: Options = {
    data: {
        name: 'foo'
    }
};

export default 导出

// types/foo/index.d.ts

export default Directions;

declare enum Directions {
    Up,
    Down,
    Left,
    Right
}

export =

// 整体导出
module.exports = foo;
// 单个导出
exports.bar = bar;
//导入
// 整体导入
const foo = require('foo');
// 单个导入
const bar = require('foo').bar;

UMD库 的 export as namespace

  • 既可以通过 <script> 标签引入,又可以通过 import 导入的库,称为UMD
// types/foo/index.d.ts

export as namespace foo;
export default foo;

declare function foo(): string;
declare namespace foo {
    const bar: number;
}

直接扩展全局变量

interface String {
    prependHello(): string;
}

'foo'.prependHello();

declare globalnpm 包或 UMD 库中扩展全局变量

// types/foo/index.d.ts

declare global {
    interface String {
        prependHello(): string;
    }
}

export {};
//使用
// src/index.ts
//注意即使此声明文件不需要导出任何东西,仍然需要导出一个空对象,用来告诉编译器这是一个模块的声明文件,而不是一个全局变量的声明文件。

'bar'.prependHello();

内置对象

ECMAScript 的内置对象

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 的内置对象

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

猜你喜欢

转载自blog.csdn.net/weixin_42204698/article/details/92667795