【问题标题】:How to resolve 'X' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'X' in TypeScript如何解决 \'X\' 可分配给类型 \'T\' 的约束,但 \'T\' 可以在 TypeScript 中使用约束 \'X\' 的不同子类型实例化
【发布时间】:2023-01-11 16:51:44
【问题描述】:

我有this TypeScript playground

export function isBlue<T extends Mesh>(
  object: unknown,
  type: T | Array<T>,
): object is BlueNodeType<T> {
  const array: Array<T> = Array.isArray(type) ? type : [type]
  return (
    object != null && typeof object === 'object' &&
    'type' in object &&
    typeof object.type === 'string' &&
    array.includes((object as BlueNodeType<T>).type)
  )
}

export enum Mesh {
  Assertion = 'mesh-assertion',
}

export type BlueBaseType = {
  color: 'blue'
}

export type BlueAssertionType = BlueBaseType & {
  type: Mesh.Assertion
}

export type BlueMappingType = {
  'mesh-assertion': BlueAssertionType
}

export type BlueNodeType<T extends Mesh> = BlueMappingType[T]

它抛出这个错误:

Argument of type 'Mesh' is not assignable to parameter of type 'T'.
  'Mesh' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Mesh'.(2345)

我如何让它工作?在我的真实代码库中,我有一个包含 40 种类型的 BlueMappingType,所以我希望它能够根据泛型类型参数选择正确的类型。

【问题讨论】:

标签: typescript


【解决方案1】:

使用 Array.prototype.includes 是一个棘手的问题。为了让它工作,你可以试试我的自定义includes

const withTuple = <
  List extends string[]
>(list: readonly [...List]) =>
  (prop: string): prop is List[number] =>
    list.includes(prop)

export function isBlue<T extends Mesh>(
  object: unknown,
  type: T | Array<T>,
): object is BlueNodeType<T> {
  const array: Array<T> = Array.isArray(type) ? type : [type]
  const includes = withTuple(array)
  return (
    object != null && typeof object === 'object' &&
    'type' in object &&
    typeof object.type === 'string' &&
    includes(object.type)
  )
}

export enum Mesh {
  Assertion = 'mesh-assertion',
}

export type BlueBaseType = {
  color: 'blue'
}

export type BlueAssertionType = BlueBaseType & {
  type: Mesh.Assertion
}

export type BlueMappingType = {
  'mesh-assertion': BlueAssertionType
}

export type BlueNodeType<T extends Mesh> = BlueMappingType[T]

Playground

withTuple 只是 Array.prototype.includes 的柯里化版本,但它适用于元组。

您可以查看我的article 以获取更多示例

【讨论】:

    猜你喜欢
    • 2019-12-13
    • 2021-12-10
    • 1970-01-01
    • 2022-01-20
    • 2020-11-25
    • 2021-06-19
    • 2021-10-14
    • 2021-02-13
    • 2021-05-22
    相关资源
    最近更新 更多