typescript - 有沒有方法可以透過名稱(字串)來解析類型?
我試著查看 redux 的 createSlice 是如何運作的,但沒有成功。
範例:
import { createSlice } from '@reduxjs/toolkit'
const counterSlice = createSlice({
name: 'counter',
initialState: 0,
reducers: {
increment: (state) => state + 1,
},
})
// The editor aware of `counterSlice.actions.increment`
它是如何運作的?
回到主題,有沒有辦法根據給定的名稱解析類型?例如:
class Resolver {
register( name, type ) {
// Do something
}
get( name ) {
// return the Type.
}
}
// The editor should aware of the type that been registered
謝謝。
答案#1
你可以在某種程度上做到這一點。首先,你不能註冊類型,類型在運行時不存在,你可以註冊特定類型的值。
根據你想如何登記這些數值,有幾種選擇:
你可以讓 register 返回具有不同類型的解析器,該類型包含有關新註冊類型的信息:
class Resolver<T extends Record<string, unknown> = {}> {
private values = {} as T;
register<N extends PropertyKey, V extends unknown>(name: N, type: V): Resolver<T & Record<N, V>> {
let self = this as Resolver<Record<N, V>>
self.values[name] = type
return this as any;
}
get<N extends keyof T>(name: N): T[N] {
return this.values[name]
}
}
const r = new Resolver()
.register("A", () => "")
.register("B", 0);
let v1 = r.get("A"); // () => ""
let v2 = r.get("B"); // number
遊樂場連結
如果你想將值註冊到單一檔案中,你可以讓 register 成為自訂型別斷言:
class Resolver<T extends Record<string, unknown> = {}> {
private values = {} as T;
register<N extends PropertyKey, V extends unknown>(name: N, type: V): asserts this is Resolver<T & Record<N, V>> {
let self = this as Resolver<Record<N, V>>
self.values[name] = type
}
get<N extends keyof T>(name: N): T[N] {
return this.values[name]
}
}
const r: Resolver = new Resolver()
r.register("A", () => "");
r.register("B", 0);
let v1 = r.get("A"); // () => ""
let v2 = r.get("B"); // number
// Lock in the type before we export
export const finalR = r;
遊樂場連結
或者,如果只有一個 r 的實例,你可以使用介面合併來向介面添加項目:
interface ResolverValues {
}
class Resolver {
private values = {} as ResolverValues;
register<N extends keyof ResolverValues>(name: N, type: ResolverValues[N]) {
this.values[name] = type
}
get<N extends keyof ResolverValues>(name: N): T[N] {
return this.values[name]
}
}
const r: Resolver = new Resolver()
const A = () => "";
// if in another module you can use module augmentation
// declare module "./module-with-resolver" { interface ResolverValues { "A": typeof A } }
interface ResolverValues { "A": typeof A }
r.register("A", A);
const B = 0;
interface ResolverValues { "B": typeof B }
r.register("B", B);
let v1 = r.get("A"); // () => ""
let v2 = r.get("B"); // number
遊樂場連結
