TS

  1. 基本数据类型(boolean, number, string; 数组,元组,枚举;  undefined, null; any, void; never;object)
    • 元组类型
let tuple: [string, number, boolean];
tuple = ['a', 1, true];      // 长度必须跟定义时的一致,每个元素也要跟定义时的一一对应
    • 枚举类型
// 没有指定序号
enum Role {
    SUPER_ADMIN,
    ADMIN,
    USER
}

console.log(Role.SUPER_ADMIN) // 0 
console.log(Role.ADMIN) // 1 
console.log(Role.USER) // 2 
// 指定序号
enum Role {
    SUPER_ADMIN = 8,
    ADMIN = 9,
    USER =1
}

console.log(Role.SUPER_ADMIN) // 8
console.log(Role.ADMIN) // 9
console.log(Role.USER) // 1
// 不从头指定序号
enum Role {
    SUPER_ADMIN,
    ADMIN = 9,
    USER 
}

console.log(Role.SUPER_ADMIN) // 0
console.log(Role.ADMIN) // 9
console.log(Role.USER) // 10(递增的结果)
// 由序号找到对应的枚举值
enum Role {
    SUPER_ADMIN = 8,
    ADMIN = 9,
    USER =1
}

console.log(Role[8]) // SUPER_ADMIN
console.log(Role[9]) // ADMIN
console.log(Role[1]) // USER
    • never类型
// 1. 报错函数的返回类型
const  errorFunc = (str: string): never => {
    throw new Error(str);
}

// 2. 死循环
const infiniteFunc = () : never => {
    while(true) {}
}

never类型是其他任何类型的子类型,可以将never类型值赋给其他类型。

let neverVal = (() => {
    while(true) {}
})();
//neverVal 是 never 类型
let num: number = neverVal; // 不会报错

  2. 类型断言

let getLength = (target: string | number)  => {
    if ((target as string).length || (target as string).length === 0) {
        return (target as string).length;
    }
    return target.toString().length;
}
// 例子中参数是联合类型,如果不使用类型断言,橘色部分的target变量会被TS判断为没有length属性而报错;只有再使用的时候将其断言为string类型,才可消除报错

 

  3. 接口混合

下面这个例子定义了一个计数器,没有将其定义为全局变量( 避免被污染)。

interface Counter {
    (): counter;
    count: number;
}

// 注意:这里是返回值是Counter类型
const getCounter = (): Counter => {
    const c = () => {
        c.count++;
    };
    c.count  = 0;
    return c;
}

const counter: Counter = getCounter();

counter();
console.log(counter.count); // 1

    4. 类型别名 type

type IString = string; // 定义后可以在其他地方使用IString声明变量,等同string

type AddFunction = (num1: number, num2: number, num3?: number) => number // 函数类型的类型别名

let addFunction: AddFunction;
addFunction = (num1: number, num2: number) => num1 + num2;
addFunction = (num1: number, num2: number, num3: number) => num1 + num2 + num3;
 
  • 类型别名type 与 接口interface的区别:
    1. 一般情况下,通过interface定义的类型,可以使用type达到同样的效果(注意type定义时要加 = )。
    2. interface可以通过extends进行扩展,type 通过 & 进行扩展
    3. 可以通过定义同名接口为现有类型增加字段,而type不可以同名
type Point = {
    x: number;
  y: number;
};
type SpecialPoint = Point & {
       name: string;
}

interface Point {
    x: number;
  Y: number;
};
interface SpecialPoint extends Point {
    name: string;
}

 

  • 函数  
    •  函数参数默认值
let addFunc = (x: number, y = 3) => x+3;

console.log(addFunc(1)); // 4

console.log(addFunc(4, 5)); // 9

console.log(addFunc(4, 'a')); // 报错,第二个参数只能是number类型值
    • 函数剩余参数
let funct1 = (arg1: number, ...args: number[]): number  => {
    // ....
}
    • 函数重载(只能使用function进行重载类型的定义,不能使用interface或者type)
// 函数重载类型声明
function handleFunc (arg1: string) : string[];
function handleFunc (arg1: number) : number[];

// 函数实体定义
function handleFunc(arg1: any): any[] {
    if (typeof arg1 === 'string) {
        return arg1.split('');
    } else if (typeof arg1 === 'number') {
        return arg1.toString().split('').map(item  => Number(item));
    }
}
  •  泛型
const getArray = (value: any, times: number) : any[] => {
    return new Array(times).fill(value);
};

// 1. value 是string类型,且对得到的数组进行处理
console.log(getArray('abc', 2).map(item => item?.length)); // [3,3];
// 2. value 是number类型,number上没有length属性,但TS并没有给我们提示
console.log(getArray(4, 2).map(item => item?.length));  // [undefined, undefined]

为了解决上述问题,引入泛型。

const getArray = <T>(value: T, times: number) : T[] => {
    return new Array(times).fill(value);
}

console.log(getArray<number>(4, 2).map(item => item?.length));
// 此时, 由于泛型变量的存在,TS得知getArray返回值是一个number类型的数组,在item取length属性时会报错。

在定义函数时,可以使用多个泛型变量来帮助我们更好地定义类型。

const getTupleArray = <T, U>(param1: T, param2: U, times: number): [T, U][] => {
    return new Array(times).fill([param1, param2]);
}

console.log(getTupleArray<number, string>(4, 'abc', 2)); // [[4, 'abc'], [4, 'abc']] 返回的是元组类型的数组

 

利用泛型定义函数的类型

let getArrayFunc = <T>(arg: T, times: number) => T[];
getArrayFunc = (arg: any, times: number) => {
    return new Array(times).fill(arg);
}
// 虽然在定义函数实体时,我们使用了any定义参数类型,但由于的函数类型定义时使用了泛型,所以TS会判断出得到的数组类型是number[], 调用length时报错
getArrayFunc(6, 2).map(item => item.length);

利用类型别名与泛型来定义函数类型

type getArrayFunc = <T>(arg: T, times: number) => T[]
let getArrayFunc = (arg: string, times: number) => {
    return new Array(times).fill(arg);
}

getArrayFunc('cc', 3).forEach(item => {
    console.log(item.length);
}

// 2
// 2
// 2

利用接口和泛型定义函数类型

// 在外层定义的泛型变量, 在接口里面任何位置都能取到
interface getArray<T> {
    (arg: T, times: number) => T[];
    count: T;
}

 

  • 泛型约束
// 使泛型变量T必须具备length属性
interface ValueWithLength {
    length: number;
}

const getArray = <T extends ValueWithLength>(arg: T, times: number): T[] => {
    return new Array(times).fill(arg);
}

// 类型本身有length属性,或者对象有length属性
getArray('ad', 2);
getArray([2,3], 3);
getArray({
    length: 6
}, 4);

getArray(2, 3); // 2没有length属性,报错

泛型约束与索引的联合使用

let obj = {
  'a': 'a',
   'name'; 'cc'
};
// keyof T,得到泛型T上面所有key组成的数组  
const getProp = <T, K extends keyof T>(obj: T, propName: K) => {
    return obj[propName];
}

getProp(obj, 'a'); // a
getProps(obj, 'b');  // 报错

 

 

 

  • 文字断言
// 调用priteByFormat 时第二个参数只能是 ‘left’ | ‘right’ | ‘center’中的一个,不能是其他的值。
    function priteByFormat(str: string, alignment: ‘left’ | ‘right’ | ‘center’){
    }
    
    // 函数返回值是数字文字类型
    function compare(a: string, b: string): 0 | -1 | 1 {
        return a === b ? 0 : a > b ? 1 : -1;
    }

    // 布尔文字类型
    const text1: true = true;   // 只能赋true, 不能赋false或其他值
    const text2: false = false;  // 只能赋false, 不能赋true或其他值
    // 类型推断
    function request(url: string, method: ‘GET’ | ‘POST’ | ‘HEADER’) {
    }
    const obj = {
        url: ‘http: ilove.china.com’,
        method: ‘GET’
    };
    request(obj.url, obj.method)// 调用时,obj.method会因自动类型推断(推断为string类型)错误而报错

    // 解决方法: 在任意位置添加类型断言
    const obj = {
        url: ‘http: ilove.china.com’,
        method: ‘GET’ as ‘GET’
    };    

 

 

posted @ 2022-03-19 18:58  cecelia  阅读(560)  评论(0编辑  收藏  举报