ts类型implements后类型为never?

type ParamsA = { test: string }
type ParamsB = { test: number }

interface Base {
  create(params: unknown): void
}

class PageA implements Base {
  create(p: ParamsA) {

  }
}

class PageB implements Base {
  create(p: ParamsB) {

  }
}


let a = 1

const e = a > 1 ? new PageA() : new PageB()

e.create({ test: '1' })

image.png

这里的 create 方法参数的类型理想状态下应该是 ParamsA | ParamsB,这里为什么会是 ParamsA & ParamsB

在线查看代码

阅读 431
avatarAI BotBETA

这个问题涉及到 TypeScript 的类型推断和类型别名。

在 TypeScript 中,当你定义了两个不同的类型(在本例中是 ParamsAParamsB),并且试图用条件语句(如 let e = a > 1 ? new PageA() : new PageB())来创建这两个类型的实例时,TypeScript 并不会推断出这是一个 ParamsA | ParamsB 的类型。相反,它只会推断出这是一个 ParamsA & ParamsB 的类型。

这是因为在 TypeScript 中,当你使用条件语句来创建对象时,它不会将参数类型视为可变动的,而是将其视为固定的。也就是说,不论条件语句的条件是什么,TypeScript 都会认为你创建的对象具有相同的类型。

在你的例子中,不论 a 的值是多少,你始终在创建 PageAPageB 的实例。因此,当你尝试调用 create 方法时,TypeScript 认为你传入的参数必须是 ParamsAParamsB 的实例。

然而,在你的代码中,你传入的参数是 { test: '1' },这是一个 string 类型的值,而不是 number 类型的值。因此,当 TypeScript 尝试将这个值分配给 ParamsA & ParamsB 类型的变量时,它会产生一个错误,因为 string 类型的值不能同时是 ParamsAParamsB 的实例。

解决这个问题的一种方法是使用类型断言。你可以在调用 create 方法时明确地告诉 TypeScript 你传入的参数的类型。例如:

e.create({ test: '1' } as ParamsA)

这样,你就告诉 TypeScript 你传入的参数是一个 ParamsA 的实例,因此它就不会产生错误了。

1 个回答
✓ 已被采纳

因为 ts 不知道 e 究竟是 PageA 还是 PageB,所以传入的参数必需同时对两种情况都有效,只能取两个实现的并集

推荐问题
logo
Microsoft
子站问答
访问
宣传栏