RFC: "@cannotBeUndefined" for optional properties
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 5k
- Forks
- 162
- Avg merge
- 17h 24m
- Merged PRs (30d)
- 8
Description
Suppose an interface has optional members (possibly introduced by Partial<T>). For example:
class Person {
public name: string = '';
public age: number | undefined = undefined;
public constructor(traits: IPersonTraits = {}) {
this.update(traits);
}
public update(traits: IPersonTraits) {
if (traits.name) {
this.name = traits.name;
}
if (traits.hasOwnProperty("age")) {
this.age = traits.age;
}
}
}
interface IPersonTraits {
/**
* The person's name or `""` if not known.
*/
name?: string;
/**
* The person's age, or `undefined` if not known.
*/
age?: number | undefined;
}
TypeScript currently allows undefined to be specified for both IPersonTraits.name and IPersonTraits.age. In other words, name?: string is equivalent to name?: string | undefined, and in fact gets normalized to that in the emitted .d.ts file. This is a gap in the type system. (See https://github.com/Microsoft/TypeScript/issues/13195 which proposes to improve the language to distinguish between a missing member versus an undefined value.)
This gap can lead to bugs. For example:
let person = new Person();
// CORRECT USAGE:
person.update({
name: 'hello',
age: undefined // <-- overwrites "age" with undefined, as intended
});
// MISTAKE:
person.update({
name: undefined, // <-- assigns undefined to "name", which is not an allowed value
age: 13
});
The compiler cannot catch this mistake, and in fact the shipping .d.ts files will contain the normalized name?: string | undefined declaration, which misleadingly implies that undefined is a meaningful value for name.
A possible solution
Suppose we introduce a TSDoc modifier tag call @cannotBeUndefined, which would be used like this:
interface IPersonTraits {
/**
* The person's name or `""` if not known.
* @cannotBeUndefined
*/
name?: string;
/**
* The person's age, or `undefined` if not known.
*/
age?: number | undefined;
}
Benefits:
- The tag will be appear in the normalized .d.ts file
- The tag will be displayed in the VS Code tooltip, providing clear documentation
- We could implement a TSLint rule that looks for this tag, and if found, reports an error for an expression that is possibly
undefined
What do you think? Does this seem useful enough to be a standard tag?
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the proposed @cannotBeUndefined behavior and the linked TypeScript issue #13195. No file or test is identified, so first locate how TSDoc modifier tags are specified and tested, then establish acceptance criteria for standardizing the tag or closing the proposal.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- documentation
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 20/100