【问题标题】:Type Extension not working on generic accumulator类型扩展不适用于通用累加器
【发布时间】:2021-03-29 04:35:54
【问题描述】:

假设我有以下辅助函数:

type Entity = Readonly<{ id: string }>
type EntityEntry<T extends Entity> = readonly [string, T| null]

export const toEntityMap = <T extends Entity>(ids: ReadonlyArray<string>) => {
  return (entities: ReadonlyArray<T>): ReadonlyMap<string, T | null> => {
    return new Map(
      ids.reduce(
        (acc: ReadonlyArray<EntityEntry<T>>, cur) => {
          const entity = entities.find(e => e.id === cur)
          const entry: EntityEntry<T> = [cur, entity ?? null]
          return [...acc, entry]
        }, []
      )
    )
  }
}

我尝试这样称呼:

type Thing = Readonly<{
    id: string,
    foo: string
}>

export type ThingIds = Readonly<{
  ids: ReadonlyArray<string>
}>

type GetThings = (thingIds: ThingIds) => TaskEither<Error, ReadonlyArray<Thing>>

export type Input = Readonly<{ ids: ReadonlyArray<string> }>
export type Result = ReadonlyMap<string, Thing | null>

type Deps = Readonly<{ getThings: GetThings }>
type Ctx = ReaderTaskEither<Deps, Error, Result>

export const execute = (input: Input): Ctx => (
  (deps: Deps): TaskEither<Error, Result> => (
    pipe(
      deps.getThings(input),
      map((things) => {
        const map: ReadonlyMap<string, Thing | null> = toEntityMap(input.ids)(things)
        return map
      })
    )
  )
)

可运行链接: https://stackblitz.com/edit/typescript-tv6w7o

我希望它能够成功编译,因为 Thing 扩展了 Entity。但是,我得到了一个编译错误:

Type 'ReadonlyMap<string, Readonly<{ id: string; }>>' is not assignable to type 'ReadonlyMap<string, Readonly<{ id: string; foo: string; }>>'.
  Property 'foo' is missing in type 'Readonly<{ id: string; }>' but required in type 'Readonly<{ id: string; foo: string; }>'.(2322)

表明由于某种原因我的实用程序函数正在将地图返回到实体。

我的问题是,为什么?我该如何解决这个问题?

【问题讨论】:

标签: typescript type-coercion


【解决方案1】:

解决方案

const map: ReadonlyMap&lt;string, Thing | null&gt; = toEntityMap&lt;Thing&gt;(input.ids)(things)


说明

如果你没有指定调用toEntityMap的模板,TypeScript会推断它为Entity,而Entity不包含foo。它可能会让您感到惊讶,但您在函数内部有一个函数。在评估第一个函数时,TypeScript 无法推断您提供给第二个函数的数据。

export const toEntityMap = <T extends Entity>(ids: ReadonlyArray<string>) => {

【讨论】:

  • 非常感谢您也提供解释。你不会相信我为此拔了多少头发:)
猜你喜欢
  • 1970-01-01
  • 2023-03-25
  • 1970-01-01
  • 2020-02-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多