TypeScript文档 学习笔记(一)

858 阅读3分钟

导读

这是一篇个人学习 TypeScript 的笔记,目的是精读文档,回顾一些 JavaScript 知识并留下记录,中间会对重要的内容进行一些翻译,中间会插入一些自己的理解和补充。才疏学浅,如有不对的地方欢迎指正。

从 JavaScript 到 TypeScript

JS 和 TS 的关系非比寻常,TS 提供了所有 JS 的功能,在这些功能之上增加了一个类型检查系统。当然相比 flow 这样的类型检查工具,TypeScript 是一个门静态语言。

本文是根据 TS 官方文档的学习笔记,会做一些简单的翻译。(不少小标题名词不打算翻译,一些内容会写在)

TS的一些基础特性

静态类型检查

得益于 类型检查系统,TS 可以在程序运行之前发现一些 TypeError。这样更容易让我们找出 TypeError 并在写代码的时候就解决掉。 比如:

const message = "hello!";

message();

//This expression is not callable.
//Type 'String' has no call signatures.

如果使用 ES 执行则会跳出TypeError: message is not a function这样的错误。

非异常错误

这个其实很好理解,比如一些简单的拼写错误,一些基本逻辑的错误,又或者自己对 ES 规范理解不到位的错误,TS 都可以提前检查并指出。

//typos
const announcement = "Hello World!";

// How quickly can you spot the typos?
announcement.toLocaleLowercase();
announcement.toLocalLowerCase();

// We probably meant to write this...
announcement.toLocaleLowerCase();
function flipCoin() {
  // Meant to be Math.random()
  return Math.random < 0.5;
//Operator '<' cannot be applied to types '() => number' and 'number'.
}

TypeScript compiler

tsc 是 TypeScript 编译器,tsc 的作用应该分为两个部分,类型检查 和 编译成js。 提到 JS 编译器 就不得不说一下 babel 了,babel 其实和 tsc 不是对立的关系,babel提供了 @babel/preset-typescript 可以直接编译 ts 文件,但因为其单文件编译的特性,导致了无法为代码做类型检查和一些语言特性不可用(不过可以从写法上规避掉,const enum之类的)。 如果使用 babel 来做编译器的话,需要 tsc 用 —noEmit 先为代码做类型检查。

TypeScript 的几种基本类型

  • string
  • number
  • boolean
  • Arrays
  • Function
  • Object
  • any
  • null and undefined
  • … 不常用的类型会单独开一个章节

基础写法

Type Annotations on Variables

let myName: string = "Alice";

let myName = "Alice";
//下面这种写法也对,myName可以被推断出是'string'

Function

function greet(name: string): string {
  return "Hello, " + name.toUpperCase() + "!!"
}

Anonymous Functions

const names = ["Alice", "Bob", "Eve"];

// Contextual typing for function
names.forEach((s) => {
  console.log(s.toUppercase());
//Property 'toUppercase' does not exist on type 'string'. Did you mean 'toUpperCase'?
});

虽然匿名函数中并没有指定变量类型,但是TS可以通过上下文来推断出 s 的类型。

Object

// 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 });



// optionnal properties
function printName(obj: { first: string; last?: string }) {
  //Object is possibly 'undefined'.
  if (obj.last !== undefined) {
    // OK
    console.log(obj.last.toUpperCase());
  }
  // A safe alternative using modern JavaScript syntax:
  console.log(obj.last?.toUpperCase());
}

Union Types

// narrow the union with code
function printId(id: number | string) {
  if (typeof id === "string") {
    // In this branch, id is of type 'string'
    console.log(id.toUpperCase());
  } else {
    // Here, id is of type 'number'
    console.log(id);
  }
}

//Return type is inferred as number[]|string
// number and string both have slice method,
// so we needn't narrow the union
function getFirstThree(x: number[] | string) {
  return x.slice(0, 3);
}

Type & Interface

Type 和 interface 都可以定义一个Object Type,两者的区别是 Interface 可以向已有 interface 添加新属性,如果没有特殊原因,应优先使用interface 。

// interface
interface Window {
  title: string
}

interface Window {
  ts: TypeScriptAPI
}

const src = 'const a = "Hello World"';
window.ts.transpileModule(src, {});


//type
type Window = {
  title: string
}

type Window = {
  ts: TypeScriptAPI
}

 // Error: Duplicate identifier 'Window'.

Type Assertions

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

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

Literal Types

function printText(s: string, alignment: "left" | "right" | "center") {
  // ...
}
printText("Hello, world", "left");
printText("G'day, mate", "centre");
//error: Argument of type '"centre"' is not assignable to parameter of type '"left" | "right" | "center"'.


//interface literal
const req = { url: "https://example.com", method: "GET" };
handleRequest(req.url, req.method);
//error:Argument of type 'string' is not assignable to parameter of type '"GET" | "POST"'

//correct 1
const req = { url: "https://xxx.com", method: "GET" as "GET" };
handleRequest(req.url, req.method as "GET");

//correct 2
const req = { url: "https://xxx.com", method: "GET" } as const;
handleRequest(req.url, req.method);

null & undefined

strictNullChecks 设置为 on 时,当值为 null 或者 undefined时, 需要在使用之前对其进行检查。

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

// TS 提供了一种特殊操作符 !,用于判断非 null 或者 undefined 
function liveDangerously(x?: number | null) {
  // No error
  console.log(x!.toFixed());
}