Bug报告
我尝试在接口上使用Map类型,并希望在类实现Map接口时保留原始接口的属性文档。这通常没问题,除非Map器从原始接口中删除了一些键。下面的示例实际上表明,Omit<>
和 Omit<>
的一级别扩展可以很好地保留剩余属性的文档。然而,如果我再将其展开到一个原始Map类型表达式中,那么我突然失去了文档。
不幸的是,我无法在试图编写的代码中使用前两个选项,因为我在Map的值侧进行条件类型检查。
谢谢大家!
🔎 搜索词
omit, exclude, mapped types, documentation, tsdoc, jsdoc, properties, implements, class, hover, intellisense, vscode, quick info
🕗 版本与回归信息
- 这是我尝试的每个版本的行为,我也查阅了关于Map类型的FAQ条目
⏯ 实验场链接
带有相关代码的实验场链接
💻 代码
interface MyInterface {
/**
* Documentation for prop1
*/
prop1: number;
/**
* Documentation for prop2
*/
prop2: string;
/**
* Documentation for prop3
*/
prop3: boolean;
}
//
// 1: Omit preserves documentation! (Except for 3.3.3 as Omit wasn't added at that point)
//
type MyModifiedInterface1_DocumentationPreserved = Omit<MyInterface, 'prop3'>;
class MyClass1_DocumentationPreserved implements MyModifiedInterface1_DocumentationPreserved {
prop1 = 1; // Hover doc: Documentation for prop1
prop2 = 'a'; // Hover doc: Documentation for prop2
}
//
// 2: So does expanding Omit!
//
type MyModifiedInterface2_DocumentationPreserved = Pick<MyInterface, Exclude<keyof MyInterface, 'prop3'>>;
class MyClass2_DocumentationPreserved implements MyModifiedInterface2_DocumentationPreserved {
prop1 = 1; // Hover doc: Documentation for prop1
prop2 = 'a'; // Hover doc: Documentation for prop2
}
//
// 3: But expanding Pick causes documentaiton to be lost!
//
type MyModifiedInterface3_DocumentationLost = {
[P in Exclude<keyof MyInterface, 'prop3'>]: MyInterface[P];
};
class MyClass3_DocumentationLost implements MyModifiedInterface3_DocumentationLost {
prop1 = 1; // Hover doc missing!
prop2 = 'a'; // Hover doc missing!
}
🙁 实际行为
在VSCode中,将鼠标悬停在 MyClass3_DocumentationLost 类中的 prop1
和 prop2
时,MyInterface中的任何文档都不会显示。
🙂 预期行为
在VSCode的 MyClass3_DocumentationLost 类中,将鼠标悬停在以下属性上应该显示 MyInterface 中的相应文档:
prop1
-> "prop1的文档"prop2
-> "prop2的文档"
9条答案
按热度按时间vjhs03f71#
一个例子是这样的:
假设你有一个简单的组件,比如一个标签,它需要一些属性。
现在你有一个复合组件,它是由几个组件组成的,包括两个标签,你想在复合组件上公开这些属性,但要适当地加上前缀,以免冲突。
然后在一个消费复合组件的组件中,你可以这样做:
在这种情况下,如果
firstLabelText
和secondLabelText
上有LabelProps["text"]
的文档就更好了。这确实意味着确保你创建的文档足够通用,但它允许我在一个地方定义我的属性(与它们所属的组件共存),然后让任何额外的新属性自动过滤到暴露其组成成分属性的组件(例如,一个按钮可能有一个标签、一个图标和一个工具提示,我想让按钮自动公开底层组件的属性)。希望这样就够了。
qmb5sa222#
啊!是的,我认为这是一个很好的例子,可以重用原始文档并使其有用。
9nvpjoqh3#
我刚刚找到了一个解决这个问题的方法,虽然我知道它对性能可能不是很好:
gpnt7bae4#
See also #50715 .
I believe this type of issue is why practically every UI library out there currently copies (or generates) and duplicates most of the type-information and documentation already present in
HTMLElementTagNameMap
and all the related types - copying the documentation is either too difficult, or in some cases likely not possible.Building a typed UI library is a monumental effort - and updates to standard HTML element/attribute/event types (from official IDL definitions) really ought to come with built-in platform type definitions.
(This would be something that imperative types could potentially alleviate as well - imagine you could simply
return { docs: relatedType.docs }
and just copy the documentation from whatever type/member you want.)rpppsulh5#
为了在内存中加载信息时增加一些清晰度:这种情况发生的原因是在 checker 的
resolveMappedTypeMembers()
中,它专门检查Map类型是否使用了keyof
(isMappedTypeWithKeyofConstraintDeclaration()
),然后提取Map到的对象类型以获取原始属性。如果不这样做,就没有文档信息可以使用——属性本身的名字本身并不包含文档信息,只有它们作为属于其父对象类型的一部分时才包含文档信息。bqf10yzr6#
啊,我们开始吧!为了保留文档,它必须是一个
in keyof
,但你仍然可以使用键Map来过滤它,而不破坏文档:piztneat7#
keyof T
构造 "property" 类型,与 JSDoc 和 go-to-definition 相关联为了保持 JSDoc 和 go-to-definition,您需要使用
K in keyof ... as K
子句。Omit
内部使用了Pick
,这会将键保留为它们被转换为keyof T
时的状态。kdfy810k8#
问题是,如果你使用键Map重写键名,你将失去与原始引用属性关联的文档:
例如:
如果你在
x
上触发 intellisense,你会看到保留了文档的prop1
,但是如果你在y
上触发它,你仍然会看到prop1
,但原始源文档丢失了。我认为这可能是一个bug,因为我希望与in keyof Source
关联的文档在任何情况下都能应用,而不受名称重写的影响。我经常使用这种模式来允许为传递给子组件的属性添加前缀,例如在React中,但是文档丢失的事实很糟糕,我更希望保留文档。
jtw3ybtb9#
你有没有一个实际的例子可以提供?我的假设是,在几乎所有的情况下,如果你正在重命名键,原始文档不再完全适合。但如果有一种方法可以将它插值到Map键的新JSDoc注解中,那将是非常棒的。