【问题标题】:TypeScript parameters intersection reduced to neverTypeScript 参数交集减少到从不
【发布时间】:2021-04-06 05:01:58
【问题描述】:

如果我有这样的对象:

type GA = {
    name: 'GameA',
    duration: number
}

type GB = {
    name: 'GameB',
    duration: number
}

type Game = GA | GB;

type Initial<G extends Game = Game> = Pick<G, 'name'>

const Games = {
    GameA: {
        create: (initial: Initial<GA>): GA => {
            throw new Error('not implemented')
        }
    },
    GameB: {
        create: (initial: Initial<GB>): GB => {
            throw new Error('not implemented')
        }
    },
}

当尝试通过使用带有name(property) name: "GameA" | "GameB" 的对象来调用create 时,如下所示:

const game = Games[objectWithName.name].create(objectWithName)

报告错误:

Argument of type 'Game' is not assignable to parameter of type 'never'.
  The intersection 'Pick<GA, "name" | "duration"> & Pick<GB, "name" | "duration">' was reduced to 'never' because property 'name' has conflicting types in some constituents.
    Type 'GA' is not assignable to type 'never'.(2345)

我怎样才能正确键入我的Games 对象或objectWithName,以免参数减少为“从不”?

TypeScript Playground

【问题讨论】:

  • 您能否将Initial&lt;T&gt;GAGB 的类型定义直接添加到您的帖子中?不只是在操场上。
  • 游乐场没有错误
  • @captain-yossarian 谢谢,我已经更新了链接
  • 这个错误对我来说似乎很清楚,对象文字可以指定 only 已知属性并且您正在使用 Pick 所以持续时间不是 @987654334 类型的已知属性@。你错过了之前的错误吗?
  • 假设我有一个在 create 中填充持续时间的实现

标签: typescript


【解决方案1】:

这个typescript playground 对该问题的最小再现清楚地表明,Initial&lt;GameA&gt; 不能分配给GameA,因为 Pick 已经消除了一些必填字段。

这是您问题的根源。 goodGame 也证明了这一点,其中使用有效的 GameA 对象作为“原型”在创建调用中不会遇到问题。

type GA = {
    name: 'GameA',
    duration: number
}

type GB = {
    name: 'GameB',
    duration: number
}

type Game = GA | GB;

type Initial<G extends Game = Game> = Pick<G, 'name'>

const Games = {
    GameA: {
        create: (initial: Initial<GA>): GA => {
            throw new Error('not implemented')
        }
    },
    GameB: {
        create: (initial: Initial<GB>): GB => {
            throw new Error('not implemented')
        }
    },
}

const gameA : Game = {
    name:"GameA",
    duration:100
}

const initialGameA : Initial<Game> = {
    name:"GameA",
}

const goodGame = Games[gameA.name].create(gameA)

const badGame = Games[initialGameA.name].create(initialGameA)

【讨论】:

    猜你喜欢
    • 2017-06-12
    • 1970-01-01
    • 2015-11-02
    • 1970-01-01
    • 2020-06-27
    • 1970-01-01
    • 2012-03-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多