从TypeScript中强制对象键

gstyhher  于 2023-06-24  发布在  TypeScript
关注(0)|答案(5)|浏览(88)

假设我有

type Panel = 'store' | 'logs'

我想创建一个对象,它有key => ReactChild,其中key只是Panel中的值

const object = {
    store: StoreComponent,
    logs: LogsComponent
}

如何在这里定义object的类型?

zqry0prt

zqry0prt1#

预定义的Map类型Record就是您要查找的类型。这将采用键的联合并创建一个对象类型,其中每个属性都具有指定为类型的第二个参数的类型:

type Panel = 'store' | 'logs'

const object:Record<Panel, ReactChild> = {
    store: StoreComponent,
    logs: LogsComponent
}
bwntbbo3

bwntbbo32#

枚举和类型的组合来限制键将起作用:

enum Panel {
    store,
    logs
}

type MyObject = Partial<{ [ key in keyof typeof Panel ]: ReactChild }>

const object1: MyObject = {
    store: 2 // works
} 

const object2: MyObject = {
    whatever: 1 // invalid key
}

在我的示例中,ReactChild等于any,这只是为了演示的目的。

fdx2calv

fdx2calv3#

我认为一个enum可以满足你的要求:

enum Panel {
  Store = 'store',
  Logs = 'logs',
};

...

const object = {
  [Panel.Store]: StoreComponent,
  [Panel.Logs]: LogsComponent,
}
k7fdbhmy

k7fdbhmy4#

另一种提供可重用类型的方法可能是定义一个“键到类型”的关系,然后构造一个联合类型PaneMap,它描述Panel中每个键的值类型:

type Panel = "store" | "logs"

/*
Define reusable type relation
*/
type PanelRelation<K extends  Panel, V>  = { [key in K] : V }

/* 
Define union type describing relation of keys from Panel, to specific value types. 
This ensures that specific keys are mapped to and compatible with specific value 
types 
*/
type PanelMap = 
PanelRelation<'store', StoreComponent> & 
PanelRelation<'logs', LogsComponent>

/* Usage example */
type LogsComponent = string
type StoreComponent = number

const object:PanelMap = { 
  "store": 1,
  "logs": "x",
  // "logs": 1, <-- value type mismatch produces expected error
  // "foo": 1, <-- foo key type not in Panel produces expected error
}
fwzugrvs

fwzugrvs5#

如果你想保留object的类型,你可以使用satisfies操作符(Typescript 4.9+)。

type Panel = 'store' | 'logs'

const object = {
    store: StoreComponent,
    logs: LogsComponent
} as const satisfies Record<Panel, ReactChild>;

object['store']的类型将是StoreComponent的类型。

相关问题