如何根据对象属性值限制 vscode TypeScript IntelliSense 选项?

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

我有一个具有两个属性的对象:

type
position
type
属性的值可以是“a”或“b”。如果
position
是'a',
"top" | "bottom"
属性应该是
type
类型,或者如果
"left" | "right"
是'b',则
type
类型。

type Height = { type: 'a'; position: 'top' | 'bottom' };
type Width = { type: 'b'; position: 'left' | 'right' };
type MyObject = Height | Width;

export const myObj: MyObject = {
  position: 'right',
  type: 'a',
};

代码本身是正确的,如果

position
的值与
type
的值不兼容,将显示错误。但是,当我尝试访问
position
上的
myObj
属性时,IntelliSense 会向我显示
position
属性的所有可能选项,而不管
type
属性的值如何。

有没有办法确保 IntelliSense 只显示与

type
属性相关的选项?也就是说,当
type
为“a”时,IntelliSense 应仅显示
"top" | "bottom"
的选项,而当
type
为“b”时,IntelliSense 应仅显示
"left" | "right"
的选项。

typescript generics intellisense type-inference
1个回答
1
投票

这看起来像是 TypeScript 自动建议列表中的错误或限制。正如您所说,一旦您指定

position
,编译器就清楚地知道
type

可以接受哪些值
let myObj1: MyObject;
myObj1 = { type: 'a', position }
//                    ^^^^^^^^ 
// (property) position: "top" | "bottom"

但是您会在自动建议列表中获得所有可能的

position
值的并集。

myObj1 = { type: 'a', position: "" }
// -----------------------------^
// 🔧: "bottom"
// 🔧: "left"
// 🔧: "right"
// 🔧: "top"

我无法在 GitHub 中找到关于此的现有issue;如果有人提交了一个,它可能应该要求当输入一个 discriminated union 类型的值时,其判别属性已经被输入,字符串 literal types 的自动完成/建议列表应该被过滤到只适用于相关的那些工会会员。并做好将其作为设计限制关闭的可能性的准备;事实证明,解决这个问题会破坏其他更常见场景中的预期行为。


无论如何,除非这种情况发生变化,否则我只能提出解决方法。一种是使用

generic 辅助函数通过判别式缩小输入类型,以便编译器甚至无法使用不适用的字符串文字类型:

const asMyObject = <K extends MyObject['type']>( obj: Extract<MyObject, { type: K }> ) => obj; export const myObj: MyObject = asMyObject({ type: 'b', position: '', // -------^ // 🔧: "left" // 🔧: "right" })
如果你打算这样做,你不妨将它们分成多个参数,这对调用者来说可能更容易:

const asMyObject = <K extends MyObject['type']>( ...[type, position]: [ type: K, position: Extract<MyObject, { type: K }>['position'] ]) => ({ type, position }); export const myObj: MyObject = asMyObject('b', ''); // --------------^ // 🔧: "left" // 🔧: "right"
这两种方式都不好,但至少可以影响建议列表。

游乐场代码链接

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