typescript基础知识

61 阅读2分钟
// 枚举初始值示例
enum HttpStatus {
    OK = 200,
    Created = 201,
    BadRequest = 400,
    NotFound = 404,
}

function logStatus(status: HttpStatus) {
    console.log(`${HttpStatus[status]}: ${status}`);
}
logStatus(HttpStatus.OK); // 输出: "OK: 200" 注意:即使OK赋值为200,它的索引仍是从0开始计数
// 枚举字符串示例
enum FileAccess {
    Read = 'read',
    Write = 'write',
    Execute = 'execute',
}
console.log(FileAccess.Write); // 输出: "write"

// 元祖(和数组一样,依然可以通过下标来取值)
let tupleType: [string, boolean];
tupleType = ["semlinker", true];

// 类型断言
// let someValue: any = "this is a string";
// let strLength: number = (<string>someValue).length;
// 断言的第二种写法
let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;
// 非空断言 x! 将从 x 值域中排除 null 和 undefined 。
function myFunc(maybeString: string | undefined | null) {
    // Type 'string | null | undefined' is not assignable to type 'string'.
    // Type 'undefined' is not assignable to type 'string'. 
    const onlyString: string = maybeString; // Error
    const ignoreUndefinedAndNull: string = maybeString!; // Ok
}

// 类型守卫
// 1.in 关键字
interface Admin {
    name: string;
    privileges: string[];
}

interface Employee {
    name: string;
    startDate: Date;
}

type UnknownEmployee = Employee | Admin;

function printEmployeeInformation(emp: UnknownEmployee) {
    console.log("Name: " + emp.name);
    if ("privileges" in emp) {
        console.log("Privileges: " + emp.privileges);
    }
    if ("startDate" in emp) {
        console.log("Start Date: " + emp.startDate);
    }
}
// 4.2 typeof 关键字
function padLeft(value: string, padding: string | number) {
    if (typeof padding === "number") {
        return Array(padding + 1).join(" ") + value;
    }
    if (typeof padding === "string") {
        return padding + value;
    }
    throw new Error(`Expected string or number, got '${padding}'.`);
}
// instanceof 
interface Padder {
    getPaddingString(): string;
}

class SpaceRepeatingPadder implements Padder {
    constructor(private numSpaces: number) { }
    getPaddingString() {
        return Array(this.numSpaces + 1).join(" ");
    }
}

class StringPadder implements Padder {
    constructor(private value: string) { }
    getPaddingString() {
        return this.value;
    }
}

let padder: Padder = new SpaceRepeatingPadder(6);

if (padder instanceof SpaceRepeatingPadder) {
    // padder的类型收窄为 'SpaceRepeatingPadder'
}

// 联合类型和类型别名
const sayHello = (name: string | undefined) => {
    /* ... */
};
// 字面量类型
let num: 1 | 2 = 1;
type EventNames = 'click' | 'scroll' | 'mousemove';

// 交叉类型
// 类型别名可以通过交叉类型实现继承
type PartialPointX = { x: number; };
type Point = PartialPointX & { y: number; };
let point: Point = {
    x: 1,
    y: 1
}

// 函数
// 可选参数及默认参数
// 默认参数
// 在实际使用时,需要注意的是可选参数要放在普通参数的后面,不然会导致编译错误。
function createUserId(
    name: string = "semlinker",
    id: number,
    age?: number
): string {
    return name + id;
}
//  剩余参数
function push(array, ...items) {
    items.forEach(function (item) {
        array.push(item);
    });
}
let a = [];
push(a, 1, 2, 3);

// 函数重载
// 函数重载或方法重载是使用相同名称和不同参数数量或类型创建多个方法的一种能力。
function add(a: number, b: number): number;
function add(a: string, b: string): string;
function add(a: string, b: number): string;
function add(a: number, b: string): string;
function add(a: Combinable, b: Combinable) {
    // type Combinable = string | number;
    if (typeof a === 'string' || typeof b === 'string') {
        return a.toString() + b.toString();
    }
    return a + b;
}

// 数组相关
let x: number; let y: number; let z: number;
let five_array = [0, 1, 2, 3, 4];
[x, y, z] = five_array;
console.log(x, y, z) // 0 1 2
// 数组展开运算符
let two_array = [0, 1];
let five_array = [...two_array, 2, 3, 4];
// 数组遍历
let colors: string[] = ["red", "green", "blue"];
for (let i of colors) {
    console.log(i);
}

// 接口
interface Person {
    name: string;
    age: number;
}

let semlinker: Person = {
    name: "semlinker",
    age: 33,
};
//可选 | 只读属性
interface Person {
    readonly name: string;
    age?: number;
}
//  任意属性
interface Person {
    name: string;
    age?: number;
    [propName: string]: any;
}
const p1 = { name: "semlinker" };
const p2 = { name: "lolo", age: 5 };
const p3 = { name: "kakuqo", sex: 1 }

//接口与类型别名的区别
//接口和类型别名都可以用来描述对象的形状或函数签名:
interface Point {
    x: number;
    y: number;
}
interface SetPoint {
    (x: number, y: number): void;
}
// 不同点
//与接口类型不一样,类型别名可以用于一些其他类型,比如原始类型、联合类型和元组
// primitive
type Name = string;
// object
type PartialPointX = { x: number; };
type PartialPointY = { y: number; };
// union
type PartialPoint = PartialPointX | PartialPointY;
// tuple
type Data = [number, string];


//类
class Greeter {
    // 静态属性
    static cname: string = "Greeter";
    // 成员属性
    greeting: string;

    // 构造函数 - 执行初始化操作
    constructor(message: string) {
        this.greeting = message;
    }

    // 静态方法
    static getClassName() {
        return "Class name is Greeter";
    }

    // 成员方法
    greet() {
        return "Hello, " + this.greeting;
    }
}
let greeter = new Greeter("world");
// 类访问器
let passcode = "Hello TypeScript";
class Employee {
    private _fullName: string;

    get fullName(): string {
        return this._fullName;
    }

    set fullName(newName: string) {
        if (passcode && passcode == "Hello TypeScript") {
            this._fullName = newName;
        } else {
            console.log("Error: Unauthorized update of employee!");
        }
    }
}
let employee = new Employee();
employee.fullName = "Semlinker";
if (employee.fullName) {
    console.log(employee.fullName);
}
// 类方法重载
class ProductService {
    getProducts(): void;
    getProducts(id: number): void;
    getProducts(id?: number) {
        if (typeof id === 'number') {
            console.log(`获取id为 ${id} 的产品信息`);
        } else {
            console.log(`获取所有的产品信息`);
        }
    }
}
const productService = new ProductService();
productService.getProducts(666); // 获取id为 666 的产品信息
productService.getProducts(); // 获取所有的产品信息 

// 泛型类
class GenericNumber<T> {
    zeroValue: T;
    add: (x: T, y: T) => T;
}
let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function (x, y) {
    return x + y;
};
// 泛型工具类
//1.typeof
interface Person {
    name: string;
    age: number;
}
const sem: Person = { name: 'semlinker', age: 33 };
type Sem = typeof sem; // -> Person
function toArray(x: number): Array<number> {
    return [x];
}
type Func = typeof toArray; // -> (x: number) => number[]
//2.keyof
interface Person {
    name: string;
    age: number;
}
type K1 = keyof Person; // "name" | "age"
type K2 = keyof Person[]; // "length" | "toString" | "pop" | "push" | "concat" | "join" 
type K3 = keyof { [x: string]: Person };  // string | number
//3.in in 用来遍历枚举类型:
type Keys = "a" | "b" | "c"
type Obj = {
    [p in Keys]: any
} // -> { a: any, b: any, c: any }
// 泛型约束
interface Lengthwise {
    length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
    console.log(arg.length);
    return arg;
}
// Partial
`Partial<T>` 的作用就是将某个类型里的属性全部变为可选项 `?`。
interface Todo {
  title: string;
  description: string;
}
function updateTodo(todo: Todo, fieldsToUpdate: Partial<Todo>) {
  return { ...todo, ...fieldsToUpdate };
}
const todo1 = {
  title: "Learn TS",
  description: "Learn TypeScript",
};
const todo2 = updateTodo(todo1, {
  description: "Learn TypeScript Enum",
});
{
   title?: string | undefined;
   description?: string | undefined;
}