我有一个场景,我想根据模式 ID 验证命令并返回类型化的验证结果。为此,我需要能够推断架构 id 的枚举值。
我知道我可以为此使用泛型,例如
TSchemaId extends SchemaId
,并且它有效。然而,当我尝试从对象内部推断它时,它的行为并不像我想象的那样。
这就是我所拥有的
enum SchemaId {
SCHEMA_1 = 'SCHEMA_1',
SCHEMA_2 = 'SCHEMA_2',
}
function inferSchemaId<TSchemaId extends SchemaId> (schemaId: TSchemaId): TSchemaId {
return schemaId
}
function inferObjectSchemaId<
TSchemaId extends SchemaId,
TObjectWithSchemaId extends { schemaId: TSchemaId },
> (objectWithSchemaId: TObjectWithSchemaId): TSchemaId {
return objectWithSchemaId.schemaId
}
const si1 = inferSchemaId(SchemaId.SCHEMA_1) // SchemaId.SCHEMA_1
const si2 = inferObjectSchemaId({ schemaId: SchemaId.SCHEMA_1 }) // SchemaId
如上所示,
si1
正确缩小为 SchemaId.SCHEMA_1
,但 si2
无法缩小。
为什么会这样?我错过了什么?
奇怪的是不仅返回类型(SchemaId)而且还推断准确的值。我已经做了一个可行的案例:
enum SchemaId {
SCHEMA_1 = 'SCHEMA_1',
SCHEMA_2 = 'SCHEMA_2',
}
function inferSchemaId<TSchemaId extends SchemaId> (schemaId: TSchemaId): TSchemaId {
return schemaId
}
type ObjectWithSchemaId<T extends SchemaId> = { schemaId: T }
type InferSchemaIdFromObj<S> = S extends ObjectWithSchemaId<infer T>? T : never;
function inferObjectSchemaId<
TObjectWithSchemaId extends ObjectWithSchemaId<SchemaId>,
> (objectWithSchemaId: TObjectWithSchemaId): InferSchemaIdFromObj<TObjectWithSchemaId> {
return objectWithSchemaId.schemaId as InferSchemaIdFromObj<TObjectWithSchemaId>
}
const si1 = inferSchemaId(SchemaId.SCHEMA_1) // SchemaId.SCHEMA_1
const si2 = inferObjectSchemaId({ schemaId: SchemaId.SCHEMA_1 }) // SchemaId.SCHEMA_1