GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Index signatures for symbols and template literal strings by ahejlsberg · Pull Request #44512 · microsoft/TypeScript

Conversation

@ahejlsberg

@ahejlsberg Anders Hejlsberg (ahejlsberg) commented Jun 8, 2021 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

With this PR we implement support for symbol and template literal string index signatures. We furthermore permit index signature declarations to specify union key types, provided all constituents are either string, number, symbol, or template literal types with non-generic placeholders. Some examples:

type SymbolMap<T> = {
    [key: symbol]: T;
};

type DataProps = {
    [key: `data-${string}`]: string;
};

type PropertyMap = {
    [key: string | number | symbol]: string;
};

An index signature declaration that specifies a union key type is exactly equivalent to a set of distinct index signatures for each constituent key. For example, the PropertyMap declaration above is exactly equivalent to:

type PropertyMap = {
    [key: string]: string;
    [key: number]: string;
    [key: symbol]: string;
};

Index signature declarations are not permitted to specify literal key types or generic key types. Those kinds of types can only be used with mapped types, which map literals key types to distinct properties and defer resolution of generic key types until they're instantiated with non-generic types. For example:

type Thing<T> = Record<'a' | `foo${T}` | symbol, string>;

type StringThing = Thing<string>;  // { [a: string, [x: `foo${string}`]: string, [x: symbol]: string }
type BarThing = Thing<'bar'>;  // { [a: string, foobar: string, [x: symbol]: string }

This PR supercedes #26797 which was more ambitious but had overlap between regular properties and index signatures with literal key types that is difficult to reconcile, as well as generic index signatures for which type relationships become exceedingly complex to reason about.

Fixes #1863.
Fixes #26470.
Fixes #42192.
Fixes #44675.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

c69-addepar, shellscape, tjjfvi, kamok, blake-regalia, KostyaTretyak, chocolateboy, ExE-Boss, leidegre, MingweiSamuel, and 49 more reacted with thumbs up emoji kamok, MingweiSamuel, worstpractice, rbjakab, simonguo, and mishahrokhola reacted with laugh emoji alexrock, konsalex, zhangenming, shellscape, tjjfvi, matso94, kamok, KisaragiEffective, ntucker, ExE-Boss, and 24 more reacted with hooray emoji kamok, leidegre, MingweiSamuel, yortus, liuweiGL, VladSez, snewell92, worstpractice, dhaigh, Enteleform, and 8 more reacted with heart emoji kamok, ExE-Boss, leidegre, MingweiSamuel, MatthiasKunnen, worstpractice, netweng, KilianKilmister, Enteleform, GitSquared, and 3 more reacted with rocket emoji kamok, brainkim, andorthehood, rbjakab, simonguo, and mishahrokhola reacted with eyes emoji
All reactions
  • 👍 59 reactions
  • 😄 6 reactions
  • 🎉 34 reactions
  • ❤️ 18 reactions
  • 🚀 13 reactions
  • 👀 6 reactions
Anders Hejlsberg (ahejlsberg) added 30 commits May 31, 2021 12:28
@ahejlsberg
Switch index signature storage to 'indexInfos: IndexInfo[]' property
95dc813
@ahejlsberg
Accept new baselines
fc107dc
@ahejlsberg
Remove another usage of IndexKind enum
60cff44
@ahejlsberg
Update getIndexedAccessType and resolveMappedTypeMembers
9900302
@ahejlsberg
Accept new baselines
f27bea2
@ahejlsberg
Update grammar checking for index signatures
a064ec1
@ahejlsberg
Accept new baselines
01cb825
@ahejlsberg
Consider all index signatures in mapped types and union types
8622ae6
@ahejlsberg
Accept new baselines
7285cb9
@ahejlsberg
Update getIndexType
4bd05bc
@ahejlsberg
Accept new baselines
a91782f
@ahejlsberg
Intersect multiple applicable index signatures
730ded4
@ahejlsberg
Use getApplicableIndexInfo instead of hardwired string/number handling
c6cc9a1
@ahejlsberg
Update index signature relationship checking
bed9264
@ahejlsberg
Report type for which index signature is missing
cf0b614
@ahejlsberg
Report type for which index signature is missing
2c0bf2b
@ahejlsberg
Accept new baselines
041a12f
@ahejlsberg
Make 'number' index signatures consistently apply to numeric strings
61297e3
@ahejlsberg
Accept new baselines
7f0f4c3
@ahejlsberg
Update fourslash test
9442790
@ahejlsberg
Revise index constraint checking
f96f513
@ahejlsberg
Accept new baselines
91e3546
@ahejlsberg
Update error messages
f24a654
@ahejlsberg
Accept new baselines
f2a20cc
@ahejlsberg
Update type inference from index signatures
135e181
@ahejlsberg
Update isKnownProperty
0c27c9c
@ahejlsberg
Update contextual typing based on index signatures
b8ac093
@ahejlsberg
Accept new baselines
b2a014c
@ahejlsberg
Support union types in index signature declarations
ab96d54
@ahejlsberg
Accept new baselines
bed7008
@szmarczak Szymon Marczak (szmarczak) mentioned this pull request Aug 9, 2021
refactor: convert puppeteer to TS apify/browser-pool#37
Merged
@dohooo Caspian 東澔 (dohooo) mentioned this pull request Aug 10, 2021
Modify BorderRadiusesLiterals types. wix/react-native-ui-lib#1463
Merged
@shellscape

Andrew Powell (shellscape) commented Aug 19, 2021

Copy link
Copy Markdown

Something is amiss with this, or it's not been released yet. Still receiving the 'ol error TS1337: An index signature parameter type cannot be a union type. Consider using a mapped object type instead. errors. Ryan Cavanaugh (@RyanCavanaugh) can you confirm it's been released as of 4.3.5?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@leidegre

John Leidegren (leidegre) commented Aug 19, 2021

Copy link
Copy Markdown

Something is amiss with this, or it's not been released yet. Still receiving the 'ol error TS1337: An index signature parameter type cannot be a union type. Consider using a mapped object type instead. errors. Ryan Cavanaugh (@RyanCavanaugh) can you confirm it's been released as of 4.3.5?

It's currently in the 4.4 release which is in beta scheduled to be released by the end of August.

shellscape and dlqqq reacted with thumbs up emoji
All reactions
  • 👍 2 reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@ahejlsberg Anders Hejlsberg (ahejlsberg) mentioned this pull request Aug 23, 2021
4.4 index signature check on wrong generic? #45548
Closed
@jbalsas Chema Balsas (jbalsas) mentioned this pull request Aug 27, 2021
[RFC] TS migration patterns liferay-frontend/liferay-portal#1379
Closed
@vepanimas

Vladimir Panimaskin (vepanimas) commented Aug 30, 2021 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown

Anders Hejlsberg (@ahejlsberg) Could you please clarify why those cases work differently in terms of assignability (playground)? AFAIU for a type alias and anonymous type it uses an empty literal type from getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode without resolving its members, but is it the expected behavior?

const sym = Symbol();

function gg3(x: { [key: string]: string }, z: { [sym]: number }) {
  x = z;  // Ok
}

interface GG4 {
    [sym]: number;
}

function gg4(x: { [key: string]: string }, z: GG4) {
  x = z; // Error
}

type GG5 = {
    [sym]: number;
}

function gg5(x: { [key: string]: string }, z: GG5) {
  x = z; // Ok ?!
}
c69-addepar and ExE-Boss reacted with eyes emoji
All reactions
  • 👀 2 reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@douglasg14b

Douglas Gaskell (douglasg14b) commented Sep 6, 2021 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown

Is this in and working? I'm sitting on v4.4.2 and still receiving:

An index signature parameter type cannot be a union type. Consider using a mapped object type instead

type Test = 'one' | 'two';

export interface Foo {
    [key: Test]: any;
}
ties-s, Cristy94, f-o-w-l, saadq, 307god, and sacru2red reacted with thumbs up emoji
All reactions
  • 👍 6 reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@ahejlsberg Anders Hejlsberg (ahejlsberg) mentioned this pull request Sep 7, 2021
Enums, string/number types of interfaces/classes cannot be used as index signatures #37448
Closed
@LeonMontealegre Leon Montealegre (LeonMontealegre) mentioned this pull request Sep 24, 2021
Make factory methods for trivial Redux actions OpenCircuits/OpenCircuits#702
Open
@craigphicks

Craig P Hicks (craigphicks) commented Sep 28, 2021 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown

Douglas Gaskell (@douglasg14b)

You can do it using type and in (although not with interface).

type Test = 'one' | 'two';
type Foo= {
  [key in Test]: any;
}
//type Foo = {
//    one: any;
//    two: any;
//}

type Foo2= {
  [key in `${Test}${Test}`]: any;
}
//type Foo2 = {
//    oneone: any;
//    onetwo: any;
//    twoone: any;
//    twotwo: any;
//}

playground

I believe that because there is no "free" string or number template, this is old hat, and not related to this new feature.

douglasg14b, ExE-Boss, DevPres, steviebuilds, and markeljan reacted with thumbs up emoji
All reactions
  • 👍 5 reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@craigphicks

Craig P Hicks (craigphicks) commented Sep 28, 2021

Copy link
Copy Markdown

Anders Hejlsberg (@ahejlsberg) - This is really a great feature, thanks!

I noticed that spaces seem to count as digits with the number type. How about not allowing that?
Of course with unquoted literal labels it doesn't matter, but with quoted string indices it does.

type TP4 = {[k:`${number}`]:null}
const tp4_1:TP4 = {'1':null}
const tp4_2:TP4 = {' ':null}   // even though there is no number present, it passes
const tp4_3:TP4 = {' 1':null}
const tp4_4:TP4 = {'1 ':null}
const tp4_5:TP4 = {' 1 ':null}

playground

ExE-Boss reacted with eyes emoji
All reactions
  • 👀 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@xyuanbuilds 折木 (xyuanbuilds) mentioned this pull request Oct 20, 2021
feat: rowKey can be symbol react-component/table#688
Open
@intgr Marti Raudsepp (intgr) mentioned this pull request Nov 5, 2021
Support type-safe dictionaries where set of keys is finite #42477
Closed
@599316527

Kyle He (599316527) commented Nov 22, 2021 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown

Index signatures for template literal string with generic?

type Props<T extends string> = {
  renders: {[key in T]: any};
  [key: `render${Capitalize<T>}`]: any;
};

TS 4.5.2 says:

An index signature parameter type cannot be a literal type or generic type. Consider using a mapped object type instead.(1337)

leonardochaia, hellowalker, Thundercraft5, sacru2red, uladkasach, netotz, and jthoward64 reacted with thumbs up emoji
All reactions
  • 👍 7 reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@yusufkandemir Yusuf Kandemir (yusufkandemir) mentioned this pull request Nov 30, 2021
Interfaces that extend 'Symbol' cannot be used as 'symbol' type directly #46956
Closed
@fnky Christian Petersen (fnky) mentioned this pull request Jan 10, 2022
Improve type-safety for Grecha tag tsoding/emoteJAM#82
Open
@joebowbeer Joe Bowbeer (joebowbeer) mentioned this pull request Feb 26, 2022
Getting typing error with ClsStore interface Papooch/nestjs-cls#20
Closed
@GitKou 高喵喵 (GitKou) mentioned this pull request Mar 28, 2022
Fix InputProps supports data attributes ant-design/ant-design#34410
Merged
2 of 19 tasks
@F3n67u Feng Yu (F3n67u) mentioned this pull request Apr 11, 2022
clean @ts-expect-error jestjs/jest#12664
Merged
@trusktr Joe Pea (trusktr) mentioned this pull request Jul 7, 2022
No type error when setting an unknown property of a JSX element #42403
Open
@mhofman Mathieu Hofman (mhofman) mentioned this pull request Aug 16, 2022
Cannot use symbol as "index" for plain object property access #50319
Open
@liuyiqi1999

Liu YiQi (liuyiqi1999) commented Dec 28, 2022

Copy link
Copy Markdown
  1. If there're other keys needing restricting value type, how should I put it?
type Test = 'one' | 'two';
type Foo= {
  stringKey: string; // A mapped type may not declare properties or methods.
  numberKey: number;
  [key in Test]: any;
}

playground

  1. Can this feature be used in interfaces?
enum Test {
  ONE = 'one',
  TWO = 'two'
}
interface Foo {
  [key: Test]: any; // An index signature parameter type cannot be a literal type or generic type. Consider using a mapped object type instead.
}

playground

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@blumamir Amir Blum (blumamir) mentioned this pull request Feb 7, 2023
chore: fix contrib build open-telemetry/opentelemetry-js-contrib#1374
Merged
@wbt wbt mentioned this pull request Feb 7, 2023
[Bug]: 2.5.0 Property 'timestamp' and 'stack does not exist on type 'TransformableInfo'. winstonjs/logform#244
Closed
@airtonix

Zeno Jiricek (airtonix) commented Feb 14, 2024

Copy link
Copy Markdown
  1. If there're other keys needing restricting value type, how should I put it?

As two separate mapped objects

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

Adrien LESÉNÉCHAL (Derugon) pushed a commit to Derugon/types-mediawiki that referenced this pull request Nov 18, 2024
Adrien LESÉNÉCHAL
Update typescript to 4.4.2
43b7168
4.4.2 was the 1st npm release to allow template string pattern index signatures, used in this PR.
see microsoft/TypeScript#44512
@mkantor Matt Kantor (mkantor) mentioned this pull request Feb 21, 2025
Sometimes, keyof any is string #61203
Closed
@mrazauskas Tom Mrazauskas (mrazauskas) mentioned this pull request Jun 17, 2025
Add .isApplicableIndexType() to the TypeChecker #61886
Closed
6 tasks done
@microsoft Microsoft (microsoft) locked as resolved and limited conversation to collaborators Oct 16, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Reviewers

@weswigham Wesley Wigham (weswigham) weswigham left review comments
@RyanCavanaugh Ryan Cavanaugh (RyanCavanaugh) RyanCavanaugh approved these changes
@DanielRosenwasser Daniel Rosenwasser (DanielRosenwasser) Awaiting requested review from DanielRosenwasser

Uh oh!

There was an error while loading. Please reload this page.

Assignees

@ahejlsberg Anders Hejlsberg (ahejlsberg)

Labels

Author: Team For Backlog Bug PRs that fix a backlog bug For Milestone Bug PRs that fix a bug with a specific milestone

Projects

PR Backlog
Archived in project

Milestone

TypeScript 4.4.0 (Beta)

Development

Successfully merging this pull request may close these issues.

Object Indexing with a Template String Template literal types fail in mapped types Intuitive != expected != actual behaviour when combining string and symbol keys Allow indexing with symbols

Uh oh!

There was an error while loading. Please reload this page.

19 participants

@ahejlsberg @typescript-bot @DanielRosenwasser @andrewbranch @c69-addepar @somysz @RyanCavanaugh @kamok @leidegre @repugraf @liuweiGL @huan @shellscape @vepanimas @douglasg14b @craigphicks @599316527 @liuyiqi1999 @airtonix
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.