diff --git a/README.md b/README.md index d8d8a8e..19a4242 100644 --- a/README.md +++ b/README.md @@ -294,6 +294,25 @@ type T = [/** foo */ number, /** bar */ string]; The downlevel semantics are exactly the same as the original, but the TypeScript language service won't be able to show the member names. +### `{ [key: T]: A }` (4.4) + +Typescript 4.4 supports template literals as index signature types: + +```ts +type O = { [key: `ak${string}`]: A }; +``` + +becomes + +```ts +type O = { [key: string]: A }; +``` + +#### Semantics + +The downlevel d.ts will be less strict because an index signature would +have a more general type (`string`) instead of the original template literal type. + ### `in out T` (4.7) Typescript 4.7 supports variance annotations on type parameter declarations: diff --git a/baselines/reference/ts3.4/test.d.ts b/baselines/reference/ts3.4/test.d.ts index dd58496..5b093ab 100644 --- a/baselines/reference/ts3.4/test.d.ts +++ b/baselines/reference/ts3.4/test.d.ts @@ -71,3 +71,6 @@ export declare const foo: { export type IR = IteratorResult; /** Template Literal - supported since 4.1 < should be StringKeyword */ export type TTemplateLiteral = string; +export type TTemplateLiteralIndexSignature = { + [key: string]: number; +}; diff --git a/baselines/reference/ts3.5/test.d.ts b/baselines/reference/ts3.5/test.d.ts index ae9928a..9e0fe74 100644 --- a/baselines/reference/ts3.5/test.d.ts +++ b/baselines/reference/ts3.5/test.d.ts @@ -71,3 +71,6 @@ export declare const foo: { export type IR = IteratorResult; /** Template Literal - supported since 4.1 < should be StringKeyword */ export type TTemplateLiteral = string; +export type TTemplateLiteralIndexSignature = { + [key: string]: number; +}; diff --git a/baselines/reference/ts3.6/test.d.ts b/baselines/reference/ts3.6/test.d.ts index 5b3a6f1..d006e46 100644 --- a/baselines/reference/ts3.6/test.d.ts +++ b/baselines/reference/ts3.6/test.d.ts @@ -73,3 +73,6 @@ export declare const foo: { export type IR = IteratorResult; /** Template Literal - supported since 4.1 < should be StringKeyword */ export type TTemplateLiteral = string; +export type TTemplateLiteralIndexSignature = { + [key: string]: number; +}; diff --git a/baselines/reference/ts3.7/test.d.ts b/baselines/reference/ts3.7/test.d.ts index 89d6270..ae77f31 100644 --- a/baselines/reference/ts3.7/test.d.ts +++ b/baselines/reference/ts3.7/test.d.ts @@ -73,3 +73,6 @@ export declare const foo: { export type IR = IteratorResult; /** Template Literal - supported since 4.1 < should be StringKeyword */ export type TTemplateLiteral = string; +export type TTemplateLiteralIndexSignature = { + [key: string]: number; +}; diff --git a/baselines/reference/ts3.8/test.d.ts b/baselines/reference/ts3.8/test.d.ts index f3b3ef8..b8ca6fe 100644 --- a/baselines/reference/ts3.8/test.d.ts +++ b/baselines/reference/ts3.8/test.d.ts @@ -74,3 +74,6 @@ export declare const foo: { export type IR = IteratorResult; /** Template Literal - supported since 4.1 < should be StringKeyword */ export type TTemplateLiteral = string; +export type TTemplateLiteralIndexSignature = { + [key: string]: number; +}; diff --git a/baselines/reference/ts3.9/test.d.ts b/baselines/reference/ts3.9/test.d.ts index f3b3ef8..b8ca6fe 100644 --- a/baselines/reference/ts3.9/test.d.ts +++ b/baselines/reference/ts3.9/test.d.ts @@ -74,3 +74,6 @@ export declare const foo: { export type IR = IteratorResult; /** Template Literal - supported since 4.1 < should be StringKeyword */ export type TTemplateLiteral = string; +export type TTemplateLiteralIndexSignature = { + [key: string]: number; +}; diff --git a/baselines/reference/ts4.0/test.d.ts b/baselines/reference/ts4.0/test.d.ts index ca58587..bdac74b 100644 --- a/baselines/reference/ts4.0/test.d.ts +++ b/baselines/reference/ts4.0/test.d.ts @@ -74,3 +74,6 @@ export declare const foo: { export type IR = IteratorResult; /** Template Literal - supported since 4.1 < should be StringKeyword */ export type TTemplateLiteral = string; +export type TTemplateLiteralIndexSignature = { + [key: string]: number; +}; diff --git a/baselines/reference/ts4.1/test.d.ts b/baselines/reference/ts4.1/test.d.ts index 3810eea..7c14621 100644 --- a/baselines/reference/ts4.1/test.d.ts +++ b/baselines/reference/ts4.1/test.d.ts @@ -74,3 +74,6 @@ export declare const foo: { export type IR = IteratorResult; /** Template Literal - supported since 4.1 < should be StringKeyword */ export type TTemplateLiteral = `${string}abc${string}`; +export type TTemplateLiteralIndexSignature = { + [key: string]: number; +}; diff --git a/baselines/reference/ts4.2/test.d.ts b/baselines/reference/ts4.2/test.d.ts index 3810eea..7c14621 100644 --- a/baselines/reference/ts4.2/test.d.ts +++ b/baselines/reference/ts4.2/test.d.ts @@ -74,3 +74,6 @@ export declare const foo: { export type IR = IteratorResult; /** Template Literal - supported since 4.1 < should be StringKeyword */ export type TTemplateLiteral = `${string}abc${string}`; +export type TTemplateLiteralIndexSignature = { + [key: string]: number; +}; diff --git a/baselines/reference/ts4.3/test.d.ts b/baselines/reference/ts4.3/test.d.ts index 3810eea..7c14621 100644 --- a/baselines/reference/ts4.3/test.d.ts +++ b/baselines/reference/ts4.3/test.d.ts @@ -74,3 +74,6 @@ export declare const foo: { export type IR = IteratorResult; /** Template Literal - supported since 4.1 < should be StringKeyword */ export type TTemplateLiteral = `${string}abc${string}`; +export type TTemplateLiteralIndexSignature = { + [key: string]: number; +}; diff --git a/baselines/reference/ts4.4/test.d.ts b/baselines/reference/ts4.4/test.d.ts index 3810eea..1338cfc 100644 --- a/baselines/reference/ts4.4/test.d.ts +++ b/baselines/reference/ts4.4/test.d.ts @@ -74,3 +74,6 @@ export declare const foo: { export type IR = IteratorResult; /** Template Literal - supported since 4.1 < should be StringKeyword */ export type TTemplateLiteral = `${string}abc${string}`; +export type TTemplateLiteralIndexSignature = { + [key: `${string}abc${string}`]: number; +}; diff --git a/baselines/reference/ts4.5/test.d.ts b/baselines/reference/ts4.5/test.d.ts index 82292d4..c2c7159 100644 --- a/baselines/reference/ts4.5/test.d.ts +++ b/baselines/reference/ts4.5/test.d.ts @@ -71,3 +71,6 @@ export declare const foo: { export type IR = IteratorResult; /** Template Literal - supported since 4.1 < should be StringKeyword */ export type TTemplateLiteral = `${string}abc${string}`; +export type TTemplateLiteralIndexSignature = { + [key: `${string}abc${string}`]: number; +}; diff --git a/baselines/reference/ts4.6/test.d.ts b/baselines/reference/ts4.6/test.d.ts index 82292d4..c2c7159 100644 --- a/baselines/reference/ts4.6/test.d.ts +++ b/baselines/reference/ts4.6/test.d.ts @@ -71,3 +71,6 @@ export declare const foo: { export type IR = IteratorResult; /** Template Literal - supported since 4.1 < should be StringKeyword */ export type TTemplateLiteral = `${string}abc${string}`; +export type TTemplateLiteralIndexSignature = { + [key: `${string}abc${string}`]: number; +}; diff --git a/baselines/reference/ts4.7/test.d.ts b/baselines/reference/ts4.7/test.d.ts index 82292d4..c2c7159 100644 --- a/baselines/reference/ts4.7/test.d.ts +++ b/baselines/reference/ts4.7/test.d.ts @@ -71,3 +71,6 @@ export declare const foo: { export type IR = IteratorResult; /** Template Literal - supported since 4.1 < should be StringKeyword */ export type TTemplateLiteral = `${string}abc${string}`; +export type TTemplateLiteralIndexSignature = { + [key: `${string}abc${string}`]: number; +}; diff --git a/index.js b/index.js index 5fd4338..c2f3f41 100644 --- a/index.js +++ b/index.js @@ -367,6 +367,26 @@ function doTransform(checker, targetVersion, k) { ts.unescapeLeadingUnderscores(member.name.escapedText), /*hasTrailingNewline*/ false ); + } else if ( + semver.lt(targetVersion, "4.4.0") && + ts.isIndexSignatureDeclaration(n) && + ts.SyntaxKind.TemplateLiteralType === n.parameters[0].type.kind + ) { + const [p] = n.parameters; + return ts.factory.createIndexSignature( + n.modifiers, + [ + ts.factory.createParameterDeclaration( + p.modifiers, + p.dotDotDotToken, + p.name, + p.questionToken, + ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword), + p.initializer + ) + ], + n.type + ); } else if (semver.lt(targetVersion, "4.7.0") && ts.isTypeParameterDeclaration(n)) { return ts.factory.createTypeParameterDeclaration( n.modifiers?.filter( diff --git a/test/test.d.ts b/test/test.d.ts index 7d516f4..dabdf6d 100644 --- a/test/test.d.ts +++ b/test/test.d.ts @@ -78,3 +78,5 @@ export type IR = IteratorResult; /** Template Literal - supported since 4.1 < should be StringKeyword */ export type TTemplateLiteral = `${string}abc${string}`; + +export type TTemplateLiteralIndexSignature = { [key: `${string}abc${string}`]: number }