2.7TypeScript增强语法一览表

undefined和null类型

打开 strictNullChecks 功能,可以帮助我们发现bug。

//条件判断法
function doSomething(x: string | null) {
  if (x === null) {
    // do nothing
  } else {
    console.log("Hello, " + x.toUpperCase());
  }
}

//非空断言操作符
function liveDangerously(x?: number | null) {
  // No error
  console.log(x!.toFixed());
}

boolean,number,bigint,string,symbol,object类型

类型名称首字母正常小写。

boolean
number
bigint
string
symbol
object

联合类型

类型1 | 类型2 | 类型N..

any类型

any类型为JS支持的任意类型,等同于 :

联合(union)类型  object|class|array|symbol|string|bigint|number|boolean|null|undefined

如果没有定义一个类型,编译器无法推断您的类型,编译器会默认赋予any类型。

let obj: any;

unknown类型

unknown类型类似于any类型,但更安全,所有类型的值可赋值给unknown类型,但unknown的值只可以赋值给unknown自己或any类型。

如果unknown没有首先断言或缩小到更具体的类型,则不允许对unknown进行任何操作。

function f1(a: any) {
  a.b(); // OK
}
function f2(a: unknown) {
  a.b();
Object is of type 'unknown'.
}

void返回类型

函数没有return语句或有return语句但没有显式返回值或隐式返回undefined值,使用void返回类型。

// The inferred return type is void
function noop() {
  return;
}

never返回类型

never 是一种表示没有返回的返回类型。函数抛出异常或终止执行时,使用never返回类型。

function fail(msg: string): never {
  throw new Error(msg);
}

字面量类型

let x: "hello" = "hello";
// OK
x = "hello";
// “howdy”类型不能赋值给“hello”类型。
x = "howdy";

一个只能有一个值的类型没有多大用处!

但是通过将文字组合成并集,您可以表达一个更有用的概念——例如,函数只接受特定的一组已知值:

function printText(s: string, alignment: "left" | "right" | "center") {
  // ...
}

// OK
printText("Hello, world", "left");

// 类型 '"centre"' 实参不能赋值给类型 '"left" | "right" | "center"' 的形参.
printText("G'day, mate", "centre");

类型断言

有时候您知道关于值的类型信息,但是typescript不知道的情况下, 可以使用类型断言。

//方式一(推荐)
const myCanvas = document.getElementById("main_canvas") as HTMLCanvasElement;

//方式二(在.tsx会冲突,一般不推荐)
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.

字面量类型断言

// @errors: 2345
declare function handleRequest(url: string, method: "GET" | "POST"): void;
// ---cut---
const req = { url: "https://example.com", method: "GET" };
handleRequest(req.url, req.method);
Argument of type 'string' is not assignable to parameter of type '"GET" | "POST"'.
//解决方案一
// Change 1:
const req = { url: "https://example.com", method: "GET" as "GET" };
// Change 2
handleRequest(req.url, req.method as "GET");

//解决方案二
const req = { url: "https://example.com", method: "GET" } as const;
handleRequest(req.url, req.method);

变量

let 变量名?[: 类型注解] = 值;

常量

const 常量名[: 类型注解] = 值;

函数

function name(参数名[: 类型注解])[: 返回类型注解] {
  statements;
}

方法重写

一个派生类的方法必须遵循基类的方法契约。

class Base {
  greet() {
    console.log("Hello, world!");
  }
}
 
class Derived extends Base {
  // Make this parameter required
  greet(name: string) {
Property 'greet' in type 'Derived' is not assignable to the same property in base type 'Base'.
  Type '(name: string) => void' is not assignable to type '() => void'.
    console.log(`Hello, ${name.toUpperCase()}`);
  }
}

数组

let arr = 类型[element0, element1, ..., elementN];
//示例
number[]
string[]

元组

function doSomething(pair: [string, number]) {
  const a = pair[0];
       
const a: string
  const b = pair[1];
       
const b: number
  // ...
}
 
doSomething(["hello", 42]);

对象

可以把对象字面量创建法创建的对象直接作为类型注解。属性之间可以用 , 或 ; 分隔。

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

字段可以用readonly修饰符为前缀,限制只可以构造函数为该字段赋值,防止构造函数之外的函数给该字段赋值。

class Greeter {
  readonly name: string = "world";
 
  constructor(otherName?: string) {
    if (otherName !== undefined) {
      this.name = otherName;
    }
  }
 
  err() {
    this.name = "not ok";
Cannot assign to 'name' because it is a read-only property.
  }
}
const g = new Greeter();
g.name = "also not ok";
Cannot assign to 'name' because it is a read-only property.

类静态成员

class MyClass {
  static x = 0;
  static printX() {
    console.log(MyClass.x);
  }
}
console.log(MyClass.x);
MyClass.printX();

类成员访问控制

public:默认的访问可见性。

protected:只对子类可见,子类的对象不可显式访问。

private:只有基类自己可见。

抽象类

类、方法、字段可以是抽象的。

abstract class Base {
  abstract getName(): string;
 
  printName() {
    console.log("Hello, " + this.getName());
  }
}
 
const b = new Base();

接口

可以使用接口为任何类型命名,而不仅仅是对象类型。

//对象类型接口
interface Point {
  x: number;
  y: number;
}
 
function printCoord(pt: Point) {
  console.log("The coordinate's x value is " + pt.x);
  console.log("The coordinate's y value is " + pt.y);
}
 
printCoord({ x: 100, y: 100 });
//方法类型接口
interface Checkable {
  check(name: string): boolean;
}

接口继承

接口既可以通过继承添加属性,又可以通过打开一个已经存在的接口添加属性。

//接口:继承添加属性
interface Animal {
  name: string
}

interface Bear extends Animal {
  honey: boolean
}

//接口:打开一个已经存在的接口添加属性
interface Window {
  title: string
}

interface Window {
  ts: TypeScriptAPI
}

实现接口

类可以实现多个接口,比如class C implements A, B {.

interface Pingable {
  ping(): void;
}
 
class Sonar implements Pingable {
  ping() {
    console.log("ping!");
  }
}
 
class Ball implements Pingable {
Class 'Ball' incorrectly implements interface 'Pingable'.
  Property 'ping' is missing in type 'Ball' but required in type 'Pingable'.
  pong() {
    console.log("pong!");
  }
}

泛型

//泛型函数
function firstElement<Type>(arr: Type[]): Type | undefined {
  return arr[0];
}
//泛型数组
Array<number>
//泛型类
class Box<Type> {
  contents: Type;
  constructor(value: Type) {
    this.contents = value;
  }
}
 
const b = new Box("hello!");
//泛型接口
interface Box<Type> {
  contents: Type;
}

原创文章,作者:huoxiaoqiang,如若转载,请注明出处:https://www.huoxiaoqiang.com/javascript/javascriptlang/10209.html

发表评论

登录后才能评论