TS(四):TypeScript入门

TS(四):TypeScript入门,第1张

TypeScript入门 `tsconfig.json` - `compilerOptions``target``lib``module`、`moduleResolution``sourceMap``resolveJsonModule``isolatedModules``forceConsistentCasingInFileNames``strict``esModuleInterop``skipLibCheck`示例 数据类型 及 部分 *** 作type interface 区别`type 不可重复定义, interface 可重复定义,重复定义类型合并` 方式`扩展类型` 方式 类型断言(unknown 不知道什么类型)文字类型枚举BigInt、Symbolininstanceof类型谓语never类型 (不存在状态)调用签名构造签名限制泛型条件限制泛型返回值可选参数、默认参数索引签名泛型类keyofReturnType、typeof索引访问类型条件类型条件类型约束infer分布式条件类型继承类的执行顺序继承js中的内置类型public、protected、private类里的 static 区块 (`#data`仅供内部使用)泛型类类中的this指向is抽象类和成员ES模块CommonJS模块

tsconfig.json - compilerOptions target

使用哪种js标准进行编译

默认:ES3参数:es3 es5 es6/es2015 es2016 es2017 es2018 es2019 es2020 es2021 es2022 esnext lib

库(数组配置): 当需要ts编译的脚本在浏览器上运行时,会有 document console 等浏览器的默认方法, 可以为他配置 ‘dom’ 参数。

参数描述
ES5所有 ES3 和 ES5 功能的核心定义
ES2015ES2015(也称为 ES6)中可用的其他 API - array.find、Promise、Proxy、Symbol、Map、Set、Reflect等。
ES6“ES2015”的别名
ES2016ES2016 中可用的其他 API -array.include等。
ES7“ES2016”的别名
ES2017ES2017 中可用的其他 API - Object.entries, Object.values, Atomics, SharedArrayBuffer, date.formatToParts, 类型数组等。
ES2018ES2018 中可用的其他 API -async可迭代、promise.finally、Intl.PluralRules、regexp.groups等。
ES2019ES2019 中可用的其他 API - array.flat, array.flatMap, Object.fromEntries, string.trimStart,string.trimEnd等。
ES2020ES2020 中可用的其他 API -string.matchAll等。
ES2021ES2021 中可用的其他 API -promise.any等string.replaceAll。
ESNextESNext 中可用的其他 API - 这会随着 JavaScript 规范的发展而变化
DOMDOM定义 - window,document等。
WebWorkerWebWorker上下文中可用的 API
ScriptHost适用于Windows 脚本托管系统的 API
modulemoduleResolution

module: 设置程序的模块系统(当程序进行模块化引用脚本时,把程序编译成哪种模式)

moduleResolution: 指定模块解析策略

compilerOptions.module = 'none'compilerOptions.moduleResolution = 'node'
/* 编译前 */
// modules/index.ts
export default {
    name: '张三',
    desc: '法外狂徒'
}

// app.ts
import who from './index';

class Person {
    name: string;
    age: number;

    constructor(name: string, age: number) {
        this.name = name;
        this.age = age;
    }

    getUserInfo() {
        console.log(`${this.name} - ${this.age}`);
    }

    sayWho() {
        console.log(`${who.name} - ${who.desc}`)
    }
}

const person = new Person('Person', 25);
person.getUserInfo();
person.sayWho();
/* 编译后 */
// modules/index.d.js
"use strict";
Object.defineProperty(exports, "__esModule", {value: true});
exports.default = {
    name: '张三',
    desc: '法外狂徒'
};

// app.js
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : {"default": mod};
};
Object.defineProperty(exports, "__esModule", {value: true});
const modules_1 = __importDefault(require("./index"));

class Person {
    name;
    age;

    constructor(name, age) {
        this.name = name;
        this.age = age;
    }

    getUserInfo() {
        console.log(`${this.name} - ${this.age}`);
    }

    sayWho() {
        console.log(`${modules_1.default.name} - ${modules_1.default.desc}`);
    }
}

const person = new Person('Person', 25);
person.getUserInfo();
person.sayWho();
sourceMap

为生成的JavaScript文件创建源映射文件(xxx.js.map)

resolveJsonModule

是否允许导入带有“.json”扩展名的模块(需要moduleCommonJS类型)

isolatedModules

确保每个文件都可以安全传输,而不依赖于其他导入

forceConsistentCasingInFileNames

区分大小写

strict

严格模式

esModuleInterop

提供两个helper函数__importStar__importDefault分别处理import * asimport default

skipLibCheck

跳过声明文件的类型检查(跳过类型为 .d.ts 的所有文件)。这可以在编译期间节省时间,但会牺牲类型系统的准确性

示例
{
  "compilerOptions": {
    "target": "esnext",
    "lib": [
      "esnext",
      "dom"
    ],
    "module": "CommonJS",
    "moduleResolution": "node",
    "sourceMap": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true
  }
}
数据类型 及 部分 *** 作
interface IData {
    str: string;        // 字符串
    num: number;        // 数字
    bool: boolean;      // 布尔
    n?: null;           // null
    un?: undefined;     // undefined

    arr: any[];         // 泛型数组
    list: Array<any>;   // 泛型数组

    obj1: object;       // 对象
    obj2: object;       // 对象

    func: Function;     // 函数

    data: any;          // 泛型

    str_num: string | number; // 字符串或数字

    un_know: unknown;
}

export class Data {
    _str: string;
    _num: number;
    _bool: boolean;
    _arr: any[];
    _list: Array<any>;
    _obj1: object;
    _obj2: object;
    _data: any;
    _func: Function;
    _str_num: string | number;
    _un_know: unknown;

    constructor({str, num, bool, arr, list, obj1, obj2, func, data, str_num, un_know}: IData) {
        this._str = str;

        this._num = num;

        this._bool = bool;

        this._arr = arr;
        this._list = list;

        this._obj1 = obj1;
        this._obj2 = obj2;

        this._func = func;

        this._data = data;

        this._str_num = typeof str_num === "string" ? str_num.toUpperCase() : str_num;

        this._un_know = un_know;
    }

    getData() {
        for (const key in this) {
            console.log(key, this[key]);
        }
    }
}

const data = new Data({
    str: '张三',
    num: 18,
    bool: true,
    arr: [],
    list: ['A', 123],
    obj1: {},
    obj2: [{name: 'Person'}],
    func: () => 123,
    data: {},
    str_num: '123abc',
    un_know: [123]
});

data.getData();
type interface 区别 type 不可重复定义, interface 可重复定义,重复定义类型合并 方式
type ZhanSan = {
    name: string;
    desc: string;
}
// 以下代码报错
// type ZhanSan = {
//     age: number;
// }

interface Person {
    name: string;
}

interface Person {
    age: number;
}

export class Person {
    constructor(zs: ZhanSan, lee: Person) {
        console.log(zs, lee)
    }
}

new Person({name: '张三', desc: '法外狂徒'}, {name: 'Person', age: 25});
扩展类型 方式
// type
type Animal = {
    name: string;
}

type Bear = Animal & {
    age: number;
}

const bear: Bear = {
    name: '熊',
    age: 1
}
// interface 
interface Animal {
    name: string;
}

interface Bear extends Animal {
    age: number;
}

const bear: Bear = {
    name: '熊',
    age: 1
}
类型断言(unknown 不知道什么类型)
export class Person {
    constructor(name: string) {
        console.log(name)
    }
}

let name: unknown;

new Person(name as string);
new Person(<string>name);
文字类型
export const getUserInfo = (name: string, status: 'left' | 'right' | 'center') => {
    console.log(`${name} - ${status}`);
}
getUserInfo('Person', 'left');

报错:Argument of type ‘string’ is not assignable to parameter of type ‘“right” | “left” | “center”’

解决方法如下:

const data = {
    name: 'Person',
    status: 'right'
} as const;
export const getUserInfo = (name: string, status: 'left' | 'right' | 'center') => {
    console.log(`${name} - ${status}`);
}
getUserInfo(data.name, data.status);
const data = {
    name: 'Person',
    status: 'right' as 'right'
};
export const getUserInfo = (name: string, status: 'left' | 'right' | 'center') => {
    console.log(`${name} - ${status}`);
}
getUserInfo(data.name, data.status);
const data = {
    name: 'Person',
    status: 'right'
};

export const getUserInfo = (name: string, status: 'left' | 'right' | 'center') => {
    console.log(`${name} - ${status}`);
}
getUserInfo(data.name, data.status as 'right');
枚举
// 编译前
export enum Direction {
    Up = 1,
    Right,
    Down,
    Left
}

console.log(Direction.Up)
// 编译后
"use strict";
Object.defineProperty(exports, "__esModule", {value: true});
exports.Direction = void 0;
var Direction;
(function (Direction) {
    Direction[Direction["Up"] = 1] = "Up";
    Direction[Direction["Right"] = 2] = "Right";
    Direction[Direction["Down"] = 3] = "Down";
    Direction[Direction["Left"] = 4] = "Left";
})(Direction = exports.Direction || (exports.Direction = {}));
console.log(Direction.Up);
//# sourceMappingURL=app.js.map
BigInt、Symbol
const a: bigint = BigInt(100);
const b: bigint = 100n;
console.log(a, b, a == b, a === b); // 100n 100n true true

const c: Symbol = Symbol('name');
const d: Symbol = Symbol('name');
console.log(c, d, c == d, c === d); // Symbol(name) Symbol(name) false false
in
type Person = {
    name: string;
}

interface Animal {
    name: string;
    age: number
}

interface Other {
    name?: string;
    func: () => void;
}

const funA = (xxx: Person | Animal) => {
    console.log('name', 'name' in xxx);
    console.log('age', 'age' in xxx);
}
funA({name: 'Person', age: 25}); // name true ; age true ;


const funB = (xxx: Person | Animal | Other) => {
    console.log('name', 'name' in xxx);
    console.log('age', 'age' in xxx);
    console.log('func', 'func' in xxx);
}
funB({name: 'Dog', age: 2, func: () => 'Person'}); // name true ; age true ; func true ;
instanceof
class Person {
    private _name: string;

    constructor(name: string) {
        this._name = name;
    }
}

const person: Person = new Person('Person');
console.log(person instanceof Person); // true

const obj: object = new Object({_name: 'Person'});
console.log(obj instanceof Person); // false
类型谓语

pet is Fish

type Fish = {
    swim: () => void
};

type Bird = {
    fly: () => void
}

// 判断传参是否为Fish类型
function isFish(pet: Fish | Bird): pet is Fish {
    console.log(!!(pet as Fish).swim);
    return !!(pet as Fish).swim;
}

isFish({
    swim: () => {
    }
}); // true
isFish({
    fly: () => {
    }
}); // false
never类型 (不存在状态)
const func = (data: string | number | boolean) => {
    switch (typeof data) {
        case 'string':
            return 'string';
        case 'number':
            return 'number';
        case 'boolean':
            return 'boolean';
        default:
            const _data: never = data;
            return _data;
    }
}
let data: any; // 定义一个泛型的变量
console.log(func(data as number));
调用签名
type Person = {
    fullName: string;
    (age: number): number;
    say: () => string;
}
const func = (person: Person) => {
    console.log(`${person.fullName} - ${person(25)} ; ${person.say()}`);
}

function person(age: number): number {
    return age;
}

person.fullName = 'Person';
person.say = (): string => `张三 - 18`;

func(person); // Person - 25 ; 张三 - 18
构造签名
interface Point {
    x: number;
    y: number;
    say: () => object;
}

interface PointConstructor {
    new(x: number, y: number): Point;
}

class Point2D implements Point {
    x: number;
    y: number;

    constructor(x: number, y: number) {
        this.x = x;
        this.y = y;
    }

    say(): object {
        const data = {x: this.x, y: this.y};
        console.log(data);
        return data;
    }
}

const func = (pointConstructor: PointConstructor) => {
    new pointConstructor(1, 2).say();
}

func(Point2D);
限制泛型条件
function maxListCount<T extends { length: number }>(a: T, b: T): number {
    return a.length > b.length ? a.length : b.length;
}

console.log(maxListCount({length: 2}, [1, 2, 3, 4])); // 4
限制泛型返回值
// 以下代码报错
function maxListData<T extends { length: number }>(a: T, b: T): T {
    return a.length > b.length ? a : {length: 10}; // 报错: '{length: 10}' 不是定义的泛型T
}

// 以下代码正确
function maxListData<T extends { length: number }>(a: T, b: T): T {
    return a.length > b.length ? a : b;
}

console.log(maxListData({length: 10}, [1, 2, 3, 4])); // { length: 10 }
console.log(maxListData<string[] | number[]>(['1', '2'], [1, 2, 3, 4])); // [ 1, 2, 3, 4 ]
可选参数、默认参数
const funA = (name?: string) => console.log(name);

funA(); // undefined
funA('Person'); // Person

const funB = (name: string = 'Person') => console.log(name);

funB(); // Person
funB('Tom'); // Tom
索引签名
export {}

interface Person {
    [index: number]: string | number;

    [props: string]: string | number;

}

const person: Person = {
    0: 'PLee',
    name: 'Person',
    age: 25
}

console.log(person);
interface Person<T> {
    [index: number]: T;

    [props: string]: T;
}

const person: Person<string | number> = {
    0: 'PLee',
    name: 'Person',
    age: 25,
}

console.log(person)
class Person {
    [props: string]: number | ((s: string) => boolean);

    // error 不符合索引签名
    // name: string = 'Person';
    // ok
    age: number = 25;

    // ok
    fun() {
        return true
    }

    // error 不符合索引签名
    // fun(){
    //     return 1;
    // }

    // 构造函数不受影响
    constructor() {

    }
}
泛型类
class Person<T> {
    data: T;

    constructor(data: T) {
        this.data = data;
        console.log(this.data);
    }
}

new Person<string>('abc');
keyof
type Point = {
    x: number,
    y: number
}
type P = keyof Point;

// const p: P = 'abc'; // 报错 p只能是 'x' 或者 'y'
const p: P = Math.random() > 0.5 ? 'x' : 'y';

console.log(p);
function func<T, K extends keyof T>(obj: T, key: K) {
    console.log(obj[key])
}

// func({name: 'Person'}, 'abc'); // 报错 在泛型T中找不到abc,泛型K只能是'name'
func({name: 'Person'}, 'name');
func<object, never>({name: 'Person'}, <never>'name');
ReturnType、typeof
type Func = () => string[];
type Person = ReturnType<Func>;

const person: Person = ['Person']; // Func的返回类型是string[],那么定义的person的最终返回类型就应该是string[]
function funA(): string[] {
    return ['Person']
}

// 需求: 想要定义一个类型是funA的返回类型
// type Users = ReturnType; // 报错: funA不是一个类型,这里需要的是一个类型
type Users = ReturnType<typeof funA>;
const users: Users = ['Person'];
索引访问类型
type Person = {
    name: string,
    age: number
}

type Num = Person['age'];
type StrNum1 = Person['name' | 'age'];
type StrNum2 = Person[keyof Person];
const List = [
    {name: 'Person', age: 25},
    {name: '张三', desc: '法外狂徒'},
    {name: ['张三'], desc: '法外狂徒'},
]

type Name = typeof List[number]['name']; // 查找到的是 数组中每个元素下name的值类型
type Age = typeof List[number]['age'];
type Desc = typeof List[number]['desc'];


// const name1: Name = 1;  // error
const name2: Name = 'abc'; // ok
const name3: Name = ['1']; // ok
条件类型
interface Animal {
    name: string;
}

interface Dog extends Animal {
    woof(): void;
}

// Example1 最终返回为number
type Example1 = Dog extends Animal ? number : string;

// Example1 最终返回为string
type Example2 = RegExp extends Animal ? number : string;
条件类型的应用
interface IdLabel {
    id: number;
}

interface NameLabel {
    name: string;
}

// 重载方式
function createLabel1(id: number): IdLabel;
function createLabel1(name: string): NameLabel;
function createLabel1(idOrName: number | string): IdLabel | NameLabel;
function createLabel1(idOrName: number | string): IdLabel | NameLabel {
    throw '';
}

// 条件类型判断方式
type IdOrName<T extends number | string> = T extends number ? IdLabel : NameLabel

function createLabel2<T extends number | string>(idOrName: T): IdOrName<T> {
    throw '';
}
条件类型约束
type MessageOf<T> = T extends { message: unknown } ? T['message'] : never;

type Email = {
    message: string;
}

// Example1 最终类型为string
type Example1 = MessageOf<Email>;
const str: Example1 = 'abc';

// Example1 最终类型为never
type Example2 = MessageOf<number>;
const ex2: Example2 = 'err' as never;
infer

在条件类型表达式中,可以在 extends 条件语句中使用 infer 关键字来声明一个待推断的类型变量。

type Flatten<T> = T extends infer U ? U : never;

const num: Flatten<string | number> = 123;
const str: Flatten<string | number> = 'abc';
type Flatten<T> = T extends Array<infer U> ? U : never;

const num1: Flatten<[string, number]> = 123;
const num2: Flatten<[number]> = 123;
const str1: Flatten<[string, number]> = 'abc';
const str2: Flatten<[string]> = 'abc';
const data: Flatten<string | number> = 'a' as never; // 推断不出来所以是never
分布式条件类型
type ToArray<T> = T extends any ? T[] : never;

// StrOrNumList 最终返回类型为 string[] | number[]
type StrOrNumList = ToArray<string | number>;

const list: StrOrNumList = Math.random() > 0.5 ? [1, 2, 3] : ['a', 'b', 'c'];
type ToArray<T> = [T] extends [any] ? T[] : never;

// StrOrNumList 最终返回类型为 (string | number)[]
type StrOrNumList = ToArray<string | number>;

const list: StrOrNumList = [1, 2, 'a', 'b'];
继承类的执行顺序 1、基类的字段被初始化 Person2、基类的构造函数运行 Person3、派生类的字段被初始化 Person4、派生类的构造函数运行 Person
class Person {
    name: string;

    constructor(name: string) {
        this.name = name;
        console.log(this.name); // ProsperLee
    }
}

class Person extends Person {
    name: string = 'Person';

    constructor(name: string) {
        super(name);
        console.log(this.name) // Person
    }
}

const lee = new Person('ProsperLee');

console.log(lee); // Person { name: 'Person' }

// 'ProsperLee' ---> 'Person' ---> Person { name: 'Person' }
继承js中的内置类型
class MsgError extends Error {
    constructor(msg: string) {
        super(msg);

        // 解决低版本下找不到msgError.sayMsg方法运行报错问题,如在target为es5时
        Object.setPrototypeOf(this, MsgError.prototype);
    }

    sayMsg() {
        console.log(this.message);
    }
}

const msgError = new MsgError('ProsperLee');
msgError.sayMsg();
public、protected、private

public 公开的,任何对象内均可访问

protected 受保护的,类及子类能够访问

private 私有的,当前类内能够访问

const Person = class<T> {
    constructor(public a: T, protected b: T[], private c: number) {
        this.a = a;
        this.b = b;
        this.c = c;
    }
}

const person = new Person<string>('Person', ['a', 'b'], 10);
console.log(person.a);
// console.log(person.b); // Property 'b' is protected and only accessible within class 'Person ' and its subclasses.
// console.log(person.c); // Property 'c' is private and only accessible within class 'Person '.
类里的 static 区块 (#data仅供内部使用)
class Perosn {
    static #data = 'Person123';

    get data() {
        return Perosn.#data;
    }

    // 默认会执行
    static {
        Perosn.#data += '!@#';
    }

    static sayData() {
        console.log(Perosn.#data);
    }

    sayData() {
        console.log(Perosn.#data);
    }
}

// Property '#data' is not accessible outside class 'Perosn' because it has a private identifier.
// 属性“#data”在类“Perosn”之外不可访问,因为它有一个私有标识符。
// Perosn.#data = 'Person';

Perosn.sayData(); // Person123!@#

const person = new Perosn();
console.log(person.data); // Person123!@# (调用的get方法)
person.sayData(); // Person123!@# (调用的sayData方法)
泛型类
class Perosn<T> {
    _data: T;

    constructor(data: T) {
        this._data = data;
    }
}

const person = new Perosn<number>(123);
console.log(person._data); // 123

const person1 = new Perosn({name: 'Person'});
console.log(person1._data); // { name: 'Person' }

const person2 = new Perosn('Person');
console.log(person2._data); // Person
类中的this指向
class Person {
    data: string = 'Person';

    getData() {
        return this.data;
    }
}

const lee = new Person();

const tom = {
    data: 'Tom',
    getData: lee.getData
}

console.log(lee.getData()); // Person
console.log(tom.getData()); // Tom
class Person {
    data: string = 'Person';

    getData = () => {
        return this.data;
    }
}

const lee = new Person();

const tom = {
    data: 'Tom',
    getData: lee.getData
}

console.log(lee.getData()); // Person
console.log(tom.getData()); // Person
is
class Person<T> {
    value?: T;

    hasValue(): this is { value: T } {
        return !!this.value;
    }

    isClass<T extends Function>(target: T): this is T {
        return this instanceof target;
    }
}

class Person extends Person<any> {
}

const person: Person<any> = new Person();
const lee: Person = new Person();

console.log(person.isClass(Person));    // true
console.log(lee.isClass(Person));          // true
console.log(lee.isClass(Person));       // true

console.log(person.hasValue());         // false
person.value = 'Person';
console.log(person.hasValue());         // true
抽象类和成员

抽象类中可以没有抽象方法,但抽象方法一定在抽象类中

抽象类只能被继承,不能被实例化

派生类必须实现抽象类的抽象成员

abstract class Person<T> {

    constructor(public data: T) {
        this.data = data;
    }

    getData() {
        this.sayHello();
        return this.data;
    }

    abstract sayHello(): void;
}

class Person<T> extends Person<T> {
    sayHello() {
        console.log('Hello');
    }
}

const lee = new Person<object>({name: 'Person'});
console.log(lee.getData()); // Hello ---> { name: 'Person' }
ES模块
// 模块脚本

class Person {
    name: string = 'Person';
    age: number = 25;
}

export class Tom {
    name: string = 'Tom';
    age: number = 10;
}

export default Person;
// 入口脚本

// 1、引入方式 export default
// import Person from "./modules/Person";

// 2、引入方式 export
// import {Tom} from "./modules/Person";

// 3、引入方式 export 别名
// import {Tom as NewTom} from "./modules/Person";

// 4、引入方式 综合
import Person, {Tom, Tom as NewTom} from "./modules/Person";

// 4、引入方式 *
import * as Data from "./modules/Person";

console.log(Person, Tom, NewTom, Data.Tom, Data.default); // [class Person] [class Tom] [class Tom] [class Tom] [class Person]
CommonJS模块

$ npm i --save-dev @types/node

exports.属性
// 模块脚本

class Lee {
    name: string = 'Lee';
    age: number = 25;
}

class Tom {
    name: string = 'Tom';
    age: number = 10;
}

exports.data = {
    Lee,
    Tom
}

// 入口脚本

let person = require('./modules/Person');
console.log(person); // { data: { Lee: [class Lee], Tom: [class Tom] } }
module.exports
// 模块脚本

class Lee {
    name: string = 'Lee';
    age: number = 25;
}

class Tom {
    name: string = 'Tom';
    age: number = 10;
}

module.exports = {
    Lee,
    Tom
}

// 入口脚本

let person = require('./modules/Person');
console.log(person); // { Lee: [class Lee], Tom: [class Tom] }

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/944493.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-18
下一篇 2022-05-18

发表评论

登录后才能评论

评论列表(0条)

保存