抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

百度搜出来的 TypeScript 文档写得太简略了,以至于看完之后还是看不懂声明文件。

推荐一个 TS 手册,里面有详细的说明。

前言

TypeScript文档:

TypeScript: JavaScript With Syntax For Types. (typescriptlang.org)

这个是我刷题时碰见大佬推荐的,虽然是英文版,但是也可以开翻译来看

推荐使用 Chrome 插件:彩云翻译

彩云小译 - 在线翻译 (caiyunapp.com)

中英对照翻译,学 TypeScript 顺便把英语学了,岂不美哉!

image-20220123112625852

(虽然有些计算机专业名词给我乱翻译,TypeScript 翻译成“打字稿”,想想也挺合理的😅

type 和 interface 对比

类型别名 (type) 和接口 (interface) 非常相似,在许多情况下您可以自由地在它们之间进行选择。接口的几乎所有特性都是类型可用的,关键区别在于能不能对类型添加新的属性,而接口总是可扩展的。

Differences Between Type Aliases and Interfaces

Type aliases and interfaces are very similar, and in many cases you can choose between them freely. Almost all features of an interface are available in type, the key distinction is that a type cannot be re-opened to add new properties vs an interface which is always extendable.

类型扩展

interface接口

interface Animal {
  name: string
}
// 接口继承
interface Bear extends Animal {
  honey: boolean
}

const bear = getBear() 
bear.name
bear.honey

type 类型别名

type Animal = {
  name: string
}
// 类型合并 &
type Bear = Animal & { 
  honey: boolean 
}

const bear = getBear();
bear.name;
bear.honey;

向现有类型添加新字段

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'.

总结:接口与类型别名几乎可以一样对待,唯一区别就是类型别名不可以对现有类型扩展。

🔗TypeScript: Documentation - Everyday Types (typescriptlang.org)

对象属性强制保持常量

这个是 Literal Types (字面量) 写法:

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

printText("G'day, mate", "centre");
// Argument of type '"centre"' is not assignable to parameter of type '"left" | "right" | "center"'.Argument of type '"centre"' is not assignable to parameter of type '"left" | "right" | "center"'.

alignment 只能取 “left” | “right” | “center” ,否则报错。

此时传入对象的属性作为参数,便报错了

const text = {
  position: "left"
}
// do something...
printText("Hello, world", text.position);
// Argument of type 'string' is not assignable to parameter of type '"left" | "right"'.

Why ?

在上面的例子中。方法被推断为字符串,而不是“left”。因为代码可以在创建对象和调用函数之间进行其他操作,

在 JavaScript 中的 const, 对对象的约束仅仅是保证其地址不变,text.position 可以任意修改,TypeScript认为此代码有错误。

下面是官方举的一个例子:

In the above example req.method is inferred to be string, not "GET". Because code can be evaluated between the creation of req and the call of handleRequest which could assign a new string like "GUESS" to req.method, TypeScript considers this code to have an error.

There are two ways to work around this.

  1. You can change the inference by adding a type assertion in either location:

    // Change 1:
    const req = { url: "https://example.com", method: "GET" as "GET" };
    // Change 2
    handleRequest(req.url, req.method as "GET");Try
    

    Change 1 means “I intend for req.method to always have the literal type "GET"”, preventing the possible assignment of "GUESS" to that field after. Change 2 means “I know for other reasons that req.method has the value "GET"“.

  2. You can use as const to convert the entire object to be type literals:

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

The as const suffix acts like const but for the type system, ensuring that all properties are assigned the literal type instead of a more general version like string or number.

🔗 TypeScript: Documentation - Everyday Types (typescriptlang.org)

摒弃函数重载

因为 JavaScript 没有类型系统,不可以对函数重载

TypeScript 有了类型系统,可以实现重载了,但官方不推荐使用重载,因为有强大的 union types!

考虑下面几个函数

function len(s: string): number;
function len(arr: any[]): number;
function len(x: any) {
  return x.length;
}

在 TypeScript 调用他们

len(""); // OK
len([0]); // OK
len(Math.random() > 0.5 ? "hello" : [0]);
/*
No overload matches this call.
  Overload 1 of 2, '(s: string): number', gave the following error.
    Argument of type 'number[] | "hello"' is not assignable to parameter of type 'string'.
      Type 'number[]' is not assignable to type 'string'.
  Overload 2 of 2, '(arr: any[]): number', gave the following error.
    Argument of type 'number[] | "hello"' is not assignable to parameter of type 'any[]'.
      Type 'string' is not assignable to type 'any[]'. */

对于模糊不定的调用,TypeScript 会给出报错,毕竟人家是静态代码检查工具!

更好的办法是使用 union types (联合类型)

function len(x: any[] | string) {
  return x.length;
}

Always prefer parameters with union types instead of overloads when possible

🔗TypeScript: Documentation - More on Functions (typescriptlang.org)

类型框架

“类型框架” 这个是我自己造的词,对这个操作描述

interface Resp {
  code: number
  message: any
}

interface SuccessResp<T> extends Resp {
  code: 200
  message: T
}

interface PostResp {
  id: number
  title: string
}

const data = request.get<SuccessResp<PostResp>>();

可以将 SuccessResp 看作是一个实际类型的模板,其中 PostResp 是一个占位符,将被其他类型替换。当 TypeScript 看到 SuccessResp<PostResp>> 时,它将用 PostResp 替换 SuccessResp<PostResp>> 中的每个 message 实例,并最终处理类似响应体的内容。

🔗TypeScript: Documentation - Object Types (typescriptlang.org)

结束

以上记录是我在读文档,边读边用记录工具记下来的,挺好用的,不过貌似我的控制台会有报错

🔗 betterRunner/context-note: A note-taking chrome extension: taking notes on the web with their context. (github.com)

image-20220123125030116

评论