8000 Proposal: Supplementing Implicit Types · Issue #19550 · microsoft/TypeScript · GitHub
[go: up one dir, main page]

Skip to content
Proposal: Supplementing Implicit Types #19550
@ricklove

Description

@ricklove

In a type expression, I would like to be able to extend the implicitly known type of a value with specific type information.

The purpose is to get the most from the implicit type information and suplement it when some type information is missing.

Also, this will pull typescript even closer to ES6 by allowing common ES6 patterns like argument destructuring which results in the any type (where the type cannot currently be specified).

Syntax

// Like normal type information
const { req, opt = '', def = 'DEFAULT' }: { req: string, opt?: string, def?: string } = values;

// But 'extends' implicit typing
const { req, opt = '', def = 'DEFAULT' }: extends { req: string } = values;

The extends keyword would only modify the type information for the part of the type expression that was specified.

Useful Cases

Argument Destructuring with Type Information

Refer to: #7576 (comment)
And my comment there: #7576 (comment)

Full Typing (Absolutely no advantage from implicit type information)

export const Fun = ({ req, opt = '', def = 'DEFAULT' }: { req: string, opt?: string, def?: string }) => {
    // ...
};

Current Best Solution

This uses Pure Implicit Typing, but it requires a default parameter that allows an unintended invalid call.

export const Fun = ({ req, opt = '', def = 'DEFAULT' } = { req: '' }) => {
	// GOOD: All variables are implicitly typed
	// ...
};

export const Fun_Call = () => {
    // BAD: It is possible to call without arguments (i.e. pseudo-required)
    Fun();
    // GOOD: But if any object is given, it works right
    Fun({ req: '' });
};

With Extends

export const Fun_extends = ({ req, opt = '', def = 'DEFAULT' }: extends { req: string }) => {
    // ...
};

export const Fun_Call = () => {
    // GOOD: This is not allowed
    // Fun();
    // GOOD: An object must be given with the correct typing
    Fun({ req: '' });
};

Extending Return Values

Current Best Solution

// Complex Objects:
const ComplexReturn = () => { return { a: 'a', b: 'b', c: 'c' }; };

const obj = ComplexReturn();
const objWithD_typeofWithObject = obj as typeof obj & { d: string };

With Extends

// Complex Objects:
const ComplexReturn = () => { return { a: 'a', b: 'b', c: 'c' }; };

const objWithD_extends = ComplexReturn() as extends { d: string };

Checklist

Syntactic

  • What is the grammar of this feature?
    • 'extends' at the beginning of type expression like 'typeof' or 'keyof'
  • Are there any implications for JavaScript back-compat? If so, are they sufficiently mitigated?
    • No
  • Does this syntax interfere with ES6 or plausible ES7 changes?
    • No

Semantic

  • What is an error under the proposed feature? Show many examples of both errors and non-errors
    • The keyword would work in any type expression, just like 'keyof'
  • How does the feature impact subtype, supertype, identity, and assignability relationships?
    • For inheritance, it could be used to extend class members from their supertype
  • How does the feature interact with generics?
    • It would not change how the keyword is used with generics

Emit

  • What are the effects of this feature on JavaScript emit? Be specific; show examples
    • This is pure typing, it would be removed from runtime emit
  • Does this emit correctly in the presence of variables of type ‘any’? Features cannot rely on runtime type information
    • N/A
  • What are the impacts to declaration file (.d.ts) emit?
    • The keyword would need to by included in the declaration file typing information
  • Does this feature play well with external modules?
    • Yes

Compatibility

  • Is this a breaking change from the 1.0 compiler? Changes of this nature require strong justification
    • Unknown
  • Is this a breaking change from JavaScript behavior? TypeScript does not alter JavaScript expression semantics, so the answer here must be “no”
    • no
  • Is this an incompatible implementation of a future JavaScript (i.e. ES6/ES7/later) feature?
    • no

Other

  • Can the feature be implemented without negatively affecting compiler performance?
    • Yes
  • What impact does it have on tooling scenarios, such as member completion and signature help in editors?
    • It will provide a new type for that type expression

Metadata

Metadata

Assignees

No one assigned

    Labels

    Awaiting More FeedbackThis means we'd like to hear from more people who would be helped by this featureSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0