使用泛型从打字稿中的对象属性推断枚举

问题描述 投票:0回答:1

我有一个场景,我想根据模式 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
无法缩小。

为什么会这样?我错过了什么?

typescript generics enums typescript-generics
1个回答
0
投票

奇怪的是不仅返回类型(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

打字稿游乐场链接

© www.soinside.com 2019 - 2024. All rights reserved.