TypeScript 官方手冊翻譯計劃【七】:型別操控-型別操作符

Chor發表於2021-12-04
  • 說明:目前網上沒有 TypeScript 最新官方文件的中文翻譯,所以有了這麼一個翻譯計劃。因為我也是 TypeScript 的初學者,所以無法保證翻譯百分之百準確,若有錯誤,歡迎評論區指出;
  • 翻譯內容:暫定翻譯內容為 TypeScript Handbook,後續有空會補充翻譯文件的其它部分;
  • 專案地址TypeScript-Doc-Zh,如果對你有幫助,可以點一個 star ~

本章節官方文件地址:Keyof Type OperatorTypeof Type Operator

Keyof 型別操作符

keyof 型別操作符

keyof 型別操作符接受一個物件型別作為引數,並基於它的鍵產生一個由字串字面量或者數值字面量組成的聯合型別。下面的型別 P 等同於型別 "x" | "y"

type Point = { x: number; y: number };
type P = keyof Point;
    ^
   // type P = keyof Point     

如果 keyof 操作的型別有 string 或者 number 型別的索引簽名,那麼 keyof 會返回該索引簽名的型別:

type Arrayish = { [n: number]: unknown };
type A = keyof Arrayish;
     ^
   // type A = number
 
type Mapish = { [k: string]: boolean };
type M = keyof Mapish;
     ^
   // type M = string | number

注意,在這個例子中,M 表示的型別是 string | number —— 這是因為 JavaScript 物件的鍵總是會被強制轉化為一個字串,因此 obj[0] 等同於 obj["0"]

keyof 型別和對映型別結合的時候會發揮很大的作用,後續的章節我們也會進行介紹。

Typeof 型別操作符

typeof 型別操作符

JavaScript 中本身就有一個可用於表示式上下文的 typeof 操作符:

// 列印 "string"
console.log(typeof "Hello world");

TypeScript 則新增了一個可用於型別上下文的 typeof 操作符,讓你可以引用某個變數或者屬性的型別:

let s = "hello";
let n: typeof s;
    ^
    // let n: string

像上面這樣用於基本型別,作用並不是很大,但如果把 typeof 和其它型別操作符結合使用,就可以方便地表示多種模式了。舉個例子,我們先來看一下預定義型別 ReturnType<T>。它可以接受一個函式型別並將它的返回值型別返回出去:

type Predicate = (x: unknown) => boolean;
type K = ReturnType<Predicate>;
     ^
    // type K = boolean     

如果直接把函式名作為引數傳遞給 ReturnType,那麼我們會看到一個指示性錯誤:

function f() {
  return { x: 10, y: 3 };
}
type P = ReturnType<f>;
                  ^    
// 'f' refers to a value, but is being used as a type here. Did you mean 'typeof f'?

記住,值和型別是不一樣的,這裡應該傳入型別而不是值,因此我們可以改用 typeof 去引用值 f 的型別:

function f(){
    return {
        x: 10,
        y: 3
    };
}
type P = ReturnType<typeof f>;
     ^
   /* type P = {
        x: number;
        y: number;
     }            */   

限制

TypeScript 有意限制 typeof 可以操作的表示式型別。具體地說,tyepof 只能作用於識別符號(比如變數名)或者它們的屬性。這可以避免讓開發者編寫他們認為可以執行的但實際上不能執行的程式碼:

// 這裡應該改用 = ReturnType<typeof msgbox>
let shouldContinue: typeof msgbox("Are you sure you want to continue?");
                            ^            
// ',' expected.

相關文章