一、declare关键字

declare:就是告诉TS编译器你担保这些变量和模块存在,并声明了相应类型,编译的时候不需要提示错误

二、Vue3中报错不能将类型string分配给类型Ref<string>

const realtime = ref('');

realtime='errui';   //报错
//取值的时候ref只有唯一的属性value,想要赋值必须加上value
realtime.value='errui';//正确

三、const 断言

const x = { text: "hello" } as const;
TypeScript 3.4 引入了一个名为 const 断言的字面值的新构造。它的语法是一个类型断言,用 const 代替类型名称(例如 123 as const)断言构造新的文字表达式时,我们可以向语言发出以下信号:
该表达式中的字面类型不应被扩展(例如:不能从“hello”转换为字符串)

例子:CountActions 是这两个接口的联合。

const setCount = (n: number) => {
  return <const>{
    type: "SET_COUNT",
    payload: n,
  };
};

const resetCount = () => {
  return <const>{
    type: "RESET_COUNT",
  };
};

type CountActions = ReturnType<typeof setCount> | ReturnType<typeof resetCount>;

我们从 action creator 函数 setCount 和 resetCount 的返回类型中推断出一个很好的 action 联合。

四、类型断言

手动指定一个值的类型
语法: 值 as 类型<类型>值

1、类型断言只能够「欺骗」TypeScript 编译器,无法避免运行时的错误,反而滥用类型断言可能会导致运行时错误

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

function swim(animal: Cat | Fish) {
    (animal as Fish).swim();
}

const tom: Cat = {
    name: 'Tom',
    run() { console.log('run') }
};
swim(tom);
// Uncaught TypeError: animal.swim is not a function`

2、将一个父类断言为更加具体的子类

interface ApiError extends Error {
    code: number;
}
interface HttpError extends Error {
    statusCode: number;
}

function isApiError(error: Error) {
    if (typeof (error as ApiError).code === 'number') {
        return true;
    }
    return false;
}

3、将任何一个类型断言为 any
一方面不能滥用 as any,另一方面也不要完全否定它的作用,我们需要在类型的严格性和开发的便利性之间掌握平衡(这也是 TypeScript 的设计理念之一),才能发挥出 TypeScript 最大的价值。

五、keyof操作符

keyof操作符:是将一个类型映射为它所有成员名称的联合类型。

interface Person {
  name: string;
  age: number;
  gender: string;
}
type P = keyof Person; // "name" | "age" | "gender"

// 我们可以看到,keyof将Person这个对象类型映射成了一个联合类型
// 因此我们可以更方便的操作这个联合类型

也可以写的复杂点用泛型继承/扩展类型

class Student {
  constructor(private info: Person) {}

  getInfo<T extends keyof Person>(key: T): Person[T] {
    return this.info[key];
  }
}

// T是泛型,通过keyof得到了Person的成员名的联合类型,即"name" | "age" | "gender"
// 这样就实现了限制key值的输入,这时候key只能输入"name" | "age" | "gender"
// 而也不会出现返回结果为undefined了

六、typeof操作符

typeof操作符: 在编译时获取类型

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

let person: Person = { name: 'tao', age: 18 }

//两者一样
type p1 = typeof person  
type p2 = Person

七、interface来定义函数的形状

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

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

采用函数表达式|接口定义函数的方式时,对等号左侧进行类型限制,可以保证以后对函数名赋值时保证参数个数、参数类型、返回值类型不变。

扩展泛型接口

也可以使用含有泛型的接口来定义函数的形状:

interface CreateArrayFunc {
  <T>(length: number, value: T): Array<T>;
}

let createArray: CreateArrayFunc;
createArray = function<T>(length: number, value: T): Array<T> {
  let result: T[] = [];
  for (let i = 0; i < length; i++) {
      result[i] = value;
  }
  return result;
}

createArray(3, 'x'); // ['x', 'x', 'x']

八、将lib编译器选项同时设置为dom和dom.iterable是否多余

dom.iterable向各种domapi添加了iterables的定义。如果您使用的是带有domapi的运行时环境,那么应该包含dom定义。如果您使用的运行时环境支持各种domapi上的iterable方法,那么您将包括dom.iterable。在使用运行时环境时,如果在具有iterable方法的DOM API上支持iterable方法,则将dom本身包括在内,这意味着您在尝试访问这些iterable方法时将出现类型错误。单独包含dom.iterable将不起作用,因为它会增加dom定义。


Macrohoo
25 声望2 粉丝

half is wisdom!🤔