網站搜尋

javascript - 我如何在 TypeScript 中將類型作為映射鍵使用?


我想在 TypeScript(JavaScript)的映射中存儲一些信息,並以反映類型的鍵來存儲。這是因為存儲的數據實際上是靜態的,並且是對每種類型而不是每個實例適用。

這是我目前宣告這個地圖的方式:

private static followSetsByATN: Map<number, FollowSetsPerState> = new Map();

然而,number 應該是一個類型。如何才能實現這一點?

答案#1

如果你有一個物件({})作為映射,那麼鍵必須是字串(或是會自動轉換為字串的數字)。
在這種情況下,你可以使用 toString() 方法:

class A { }
console.log(A.toString());

將會列印:

function A() {
    }

你也可以使用 name 屬性:

console.log(A.name); // "A"

你也可以覆寫 toString() 方法來返回你自己的內容:

class A {
    static toString() {
        return "class A";
    }
}
console.log(A.toString()); // "class A"

然後:

let m = {} as { [name: string]: string };
m[A.toString()] = "something";

// or
m[A.name] = "something";

如果你使用的是 Map,上述所有方法仍然有效,但你不受限於必須使用字串鍵,因此你可以使用類本身:

let m = new Map<{ new (): A }, string>();
m.set(A, A.toString());

console.log(m.get(A)); // "class A"

編輯

如果你有一個類的實例,你可以使用 constructor 屬性來獲取該類:

let a = new A();
...
m.set(a.constructor, SOME_VALUE);

constructor 屬性來自 object,它看起來是這樣的:

interface Object {
    /** The initial value of Object.prototype.constructor is the standard built-in Object constructor. */
    constructor: Function;

    ...
}

所以你總是會得到一個 Function,並且你需要進行類型轉換:

m.set(a.constructor as typeof A, SOME_VALUE);

由於你可能不知道這個類別的類型,你需要做其他的事情。
你可以轉型為 any,但那樣看起來不是很好看。

這裡有一個可行的解決方案,應該對你很有用:

interface Base { }
type BaseContructor = { new (): Base };

class A implements Base { }
class B implements Base { }

let m = new Map<BaseContructor, string>();
let a = new A();
let b = new B();

m.set(a.constructor as BaseContructor, "value");
m.set(b.constructor as BaseContructor, "value");

(在遊樂場中的程式碼)