網站搜尋

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 

遊樂場連結