参考:

对象类型

除了基元之外,你最常遇到的类型是对象类型。这指的是任何带有属性的JavaScript值,这几乎是所有的对象 为了定义一个对象类型,我们简单地列出它的属性和它们的类型。
例如,这里有一个函数,它接收一个点状对象。

  1. // The parameter's type annotation is an object type
  2. function printCoord(pt: { x: number; y: number }) {
  3. console.log("The coordinate's x value is " + pt.x);
  4. console.log("The coordinate's y value is " + pt.y);
  5. }
  6. printCoord({ x: 3, y: 7 });

在这里,我们给参数注解了一个有两个属性的类型—x和y—它们都是数字类型。你可以用,或;来分隔这些属性,最后一个分隔符是可选的,无论如何。
每个属性的类型部分也是可选的。如果你没有指定一个类型,它将被假定为任何类型。

联合类型

TypeScript 的类型系统允许你使用大量的操作符从现有的类型中建立新的类型。现在我们知道如何编写一些类型,是时候开始以有趣的方式组合它们了。

定义一个联合类型

你可能看到的第一个组合类型的方法是联合类型。联合类型是一个由两个或多个其他类型组成的类型,代表可能是这些类型中任何一个的值。我们把这些类型中的每一个称为联盟的成员。
让我们写一个可以对字符串或数字进行操作的函数。

  1. function printId(id: number | string) {
  2. console.log("Your ID is: " + id);
  3. }
  4. // OK
  5. printId(101);
  6. // OK
  7. printId("202");
  8. // Error
  9. printId({ myID: 22342 });
  10. Argument of type '{ myID: number; }' is not assignable to parameter of type 'string | number'.

类型别名 Type Aliases

我们一直在使用对象类型和联合类型,把它们直接写在类型注解中。这是很方便的,但是我们经常想多次使用同一个类型,并且用一个名字来指代它。
一个类型别名正是如此—任何类型的名称。类型别名的语法是

  1. type Point = {
  2. x: number;
  3. y: number;
  4. };
  5. // Exactly the same as the earlier example
  6. function printCoord(pt: Point) {
  7. console.log("The coordinate's x value is " + pt.x);
  8. console.log("The coordinate's y value is " + pt.y);
  9. }
  10. printCoord({ x: 100, y: 100 });

比如常见的react props的类型定义
image.png
实际上,你可以使用一个类型别名来给任何类型命名,而不仅仅是一个对象类型。例如,一个类型别名可以命名一个联合类型。

  1. type ID = number | string;

比如:
image.png

接口

接口声明是命名一个对象类型的另一种方式。

  1. interface Point {
  2. x: number;
  3. y: number;
  4. }
  5. function printCoord(pt: Point) {
  6. console.log("The coordinate's x value is " + pt.x);
  7. console.log("The coordinate's y value is " + pt.y);
  8. }
  9. printCoord({ x: 100, y: 100 });

同样,常见的react props的类型也可以用接口定义
image.png

别名vs接口

类型别名和接口非常相似,而且在很多情况下,你可以在它们之间自由选择。几乎所有接口的功能都可以在类型别名中使用,关键的区别在于,类型别名不能被重新打开以添加新的属性,而接口总是可以被扩展。
image.png
比如
image.png

类型断言 Type Assertions

有时,你会拥有TypeScript无法知道的关于值的类型的信息。
例如,如果你使用 document.getElementById,TypeScript 只知道这将返回某种 HTMLElement,但你可能知道你的页面将总是有一个具有给定 ID 的 HTMLCanvasElement。
在这种情况下,你可以使用一个类型断言来指定一个更具体的类型。

  1. const myCanvas = document.getElementById("main_canvas") as HTMLCanvasElement;

像类型注解一样,类型断言会被编译器删除,不会影响你的代码的运行行为。
你也可以使用角括号语法(除非代码是在.tsx文件中,可能被识别为react组件标签),这是等同的。

  1. const myCanvas = <HTMLCanvasElement>document.getElementById("main_canvas");

提醒您。因为类型断言是在编译时删除的,所以没有与类型断言相关的运行时检查。如果类型断言是错误的,就不会有异常或空值产生。
TypeScript只允许类型断言转换为一个类型的更具体或更不具体的版本。这条规则防止了 “不可能 “的胁迫,比如。

const x = “hello” as number; Conversion of type ‘string’ to type ‘number’ may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to ‘unknown’ first.

有时这条规则可能过于保守,会不允许可能有效的更复杂的胁迫。如果发生这种情况,你可以使用两个断言,首先是对任意(或未知),然后是对所需类型。

const a = (expr as any) as T