Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

AST cleanup: type parameter inTSMappedType #6433

Closed
Assignees
JoshuaKGoldberg
Labels
ASTPRs and Issues about the AST structureaccepting prsGo ahead, send a pull request that resolves this issuebreaking changeThis change will require a new major version to be releasedlocked due to agePlease open a new issue if you'd like to say more. See https://typescript-eslint.io/contributing.
Milestone
@bradzacher

Description

@bradzacher
typeMappedType={[KeyinType]:Value;};

Mapped types are a self-contained thing in TS; they can declare exactly one signature - the index signature defining the mapping. They can declare no other properties.
As such we emit a special AST node for them -TSMappedType

exportinterfaceTSMappedTypeextendsBaseNode{
type:AST_NODE_TYPES.TSMappedType;
typeParameter:TSTypeParameter;
readonly?:boolean|'-'|'+';
optional?:boolean|'-'|'+';
typeAnnotation?:TypeNode;
nameType:TypeNode|null;
}

The problem with this AST is that we emit aTSTypeParameter for the indexer.

[KeyinType] :Value;^^^^^^^^^^^TSTypeParameter^^^.name=Identifier^^^^.constraint=TypeNode

We emit this because the underlying TS AST uses ats.TypeParameter node for this.

This is a pretty weird AST considering the following things:

  1. TSTypeParameter supports things not syntactically[1] valid in a mapped type indexer (eg variance sigils (in,out) and default valueT = Default).
  2. .constraint is marked as optional onTSTypeParameter, even though it is a syntactically[1] required.
  3. in all other usages ofTSTypeParameter the existence of the.constraint property implies theextends keyword:Name extends Constraint. However just for theTSMappedType the.constraint instead implies thein keyword:Name in Constraint.
    Note that in this location it is syntactically[1] invalid to use[Key extends Value].
  4. it's possible to define akey remapping in a mapped type. This remapping node is defined as a sibling of theTSTypeParameter, but is part of theTSMappedType node:
    typeMappedType={[KeyinTypeasRemapping]:Value;^^^^^^^^^^^TSTypeParameter^^^^^^^^^TSMappedType.nameType};

[1] Note that by syntactically valid I mean fatal parser error from TS - not just a semantic error!

It's pretty clear to me that our AST shape here is wrong and should be changed.

I propose that we switch to the following AST shape:

 export interface TSMappedType extends BaseNode {   type: AST_NODE_TYPES.TSMappedType;-  typeParameter: TSTypeParameter;+  key: Identifier;+  constraint: TypeNode;   readonly?: boolean | '-' | '+';   optional?: boolean | '-' | '+';   typeAnnotation?: TypeNode;   nameType: TypeNode | null; }

Migration Plan
With this sort of breaking AST change it can be difficult to roll out to the ecosystem without breaking the plugin ecosystem that may rely on the existing shape.
I propose the following migration plan:

  1. implement the above additions (key andconstraint) to the AST.
  2. use JSDoc to marktypeParameter as@deprecated.
  3. (optional) add test-time logging to warn consumers that they're using a deprecated, to-be-removed property.
  4. broadcast this change (perhaps via a blog post for easy sharing?).
  5. breaking change removetypeParameter in a major release.

Metadata

Metadata

Labels

ASTPRs and Issues about the AST structureaccepting prsGo ahead, send a pull request that resolves this issuebreaking changeThis change will require a new major version to be releasedlocked due to agePlease open a new issue if you'd like to say more. See https://typescript-eslint.io/contributing.

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions


    [8]ページ先頭

    ©2009-2025 Movatter.jp