Skip to content

Commit cf7cd62

Browse files
authored
Merge pull request #29435 from Microsoft/readonlyArrayTuple
Improved support for read-only arrays and tuples
2 parents d23d422 + 3324684 commit cf7cd62

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+65420
-324
lines changed

src/compiler/checker.ts

Lines changed: 139 additions & 106 deletions
Large diffs are not rendered by default.

src/compiler/diagnosticMessages.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,6 +1023,10 @@
10231023
"category": "Error",
10241024
"code": 1353
10251025
},
1026+
"'readonly' type modifier is only permitted on array and tuple types.": {
1027+
"category": "Error",
1028+
"code": 1354
1029+
},
10261030

10271031
"Duplicate identifier '{0}'.": {
10281032
"category": "Error",
@@ -2128,6 +2132,14 @@
21282132
"category": "Error",
21292133
"code": 2588
21302134
},
2135+
"Type instantiation is excessively deep and possibly infinite.": {
2136+
"category": "Error",
2137+
"code": 2589
2138+
},
2139+
"Expression produces a union type that is too complex to represent.": {
2140+
"category": "Error",
2141+
"code": 2590
2142+
},
21312143
"JSX element attributes type '{0}' may not be a union type.": {
21322144
"category": "Error",
21332145
"code": 2600

src/compiler/factory.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -876,8 +876,8 @@ namespace ts {
876876
}
877877

878878
export function createTypeOperatorNode(type: TypeNode): TypeOperatorNode;
879-
export function createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword, type: TypeNode): TypeOperatorNode;
880-
export function createTypeOperatorNode(operatorOrType: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | TypeNode, type?: TypeNode) {
879+
export function createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword, type: TypeNode): TypeOperatorNode;
880+
export function createTypeOperatorNode(operatorOrType: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword | TypeNode, type?: TypeNode) {
881881
const node = createSynthesizedNode(SyntaxKind.TypeOperator) as TypeOperatorNode;
882882
node.operator = typeof operatorOrType === "number" ? operatorOrType : SyntaxKind.KeyOfKeyword;
883883
node.type = parenthesizeElementTypeMember(typeof operatorOrType === "number" ? type! : operatorOrType);

src/compiler/parser.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2966,6 +2966,7 @@ namespace ts {
29662966
case SyntaxKind.NumberKeyword:
29672967
case SyntaxKind.BigIntKeyword:
29682968
case SyntaxKind.BooleanKeyword:
2969+
case SyntaxKind.ReadonlyKeyword:
29692970
case SyntaxKind.SymbolKeyword:
29702971
case SyntaxKind.UniqueKeyword:
29712972
case SyntaxKind.VoidKeyword:
@@ -3055,7 +3056,7 @@ namespace ts {
30553056
return finishNode(postfix);
30563057
}
30573058

3058-
function parseTypeOperator(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword) {
3059+
function parseTypeOperator(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword) {
30593060
const node = <TypeOperatorNode>createNode(SyntaxKind.TypeOperator);
30603061
parseExpected(operator);
30613062
node.operator = operator;
@@ -3077,6 +3078,7 @@ namespace ts {
30773078
switch (operator) {
30783079
case SyntaxKind.KeyOfKeyword:
30793080
case SyntaxKind.UniqueKeyword:
3081+
case SyntaxKind.ReadonlyKeyword:
30803082
return parseTypeOperator(operator);
30813083
case SyntaxKind.InferKeyword:
30823084
return parseInferType();

src/compiler/transformers/ts.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1934,8 +1934,13 @@ namespace ts {
19341934
case SyntaxKind.ConditionalType:
19351935
return serializeTypeList([(<ConditionalTypeNode>node).trueType, (<ConditionalTypeNode>node).falseType]);
19361936

1937-
case SyntaxKind.TypeQuery:
19381937
case SyntaxKind.TypeOperator:
1938+
if ((<TypeOperatorNode>node).operator === SyntaxKind.ReadonlyKeyword) {
1939+
return serializeTypeNode((<TypeOperatorNode>node).type);
1940+
}
1941+
break;
1942+
1943+
case SyntaxKind.TypeQuery:
19391944
case SyntaxKind.IndexedAccessType:
19401945
case SyntaxKind.MappedType:
19411946
case SyntaxKind.TypeLiteral:

src/compiler/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1233,7 +1233,7 @@ namespace ts {
12331233

12341234
export interface TypeOperatorNode extends TypeNode {
12351235
kind: SyntaxKind.TypeOperator;
1236-
operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword;
1236+
operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword;
12371237
type: TypeNode;
12381238
}
12391239

@@ -4063,6 +4063,7 @@ namespace ts {
40634063
export interface TupleType extends GenericType {
40644064
minLength: number;
40654065
hasRestElement: boolean;
4066+
readonly: boolean;
40664067
associatedNames?: __String[];
40674068
}
40684069

tests/baselines/reference/api/tsserverlibrary.d.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -814,7 +814,7 @@ declare namespace ts {
814814
}
815815
interface TypeOperatorNode extends TypeNode {
816816
kind: SyntaxKind.TypeOperator;
817-
operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword;
817+
operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword;
818818
type: TypeNode;
819819
}
820820
interface IndexedAccessTypeNode extends TypeNode {
@@ -2286,6 +2286,7 @@ declare namespace ts {
22862286
interface TupleType extends GenericType {
22872287
minLength: number;
22882288
hasRestElement: boolean;
2289+
readonly: boolean;
22892290
associatedNames?: __String[];
22902291
}
22912292
interface TupleTypeReference extends TypeReference {
@@ -3759,7 +3760,7 @@ declare namespace ts {
37593760
function updateParenthesizedType(node: ParenthesizedTypeNode, type: TypeNode): ParenthesizedTypeNode;
37603761
function createThisTypeNode(): ThisTypeNode;
37613762
function createTypeOperatorNode(type: TypeNode): TypeOperatorNode;
3762-
function createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword, type: TypeNode): TypeOperatorNode;
3763+
function createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword, type: TypeNode): TypeOperatorNode;
37633764
function updateTypeOperatorNode(node: TypeOperatorNode, type: TypeNode): TypeOperatorNode;
37643765
function createIndexedAccessTypeNode(objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode;
37653766
function updateIndexedAccessTypeNode(node: IndexedAccessTypeNode, objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode;
@@ -8344,7 +8345,7 @@ declare namespace ts.server {
83448345
excludedFiles: ReadonlyArray<NormalizedPath>;
83458346
private typeAcquisition;
83468347
updateGraph(): boolean;
8347-
getExcludedFiles(): ReadonlyArray<NormalizedPath>;
8348+
getExcludedFiles(): readonly NormalizedPath[];
83488349
getTypeAcquisition(): TypeAcquisition;
83498350
setTypeAcquisition(newTypeAcquisition: TypeAcquisition): void;
83508351
}

tests/baselines/reference/api/typescript.d.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -814,7 +814,7 @@ declare namespace ts {
814814
}
815815
interface TypeOperatorNode extends TypeNode {
816816
kind: SyntaxKind.TypeOperator;
817-
operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword;
817+
operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword;
818818
type: TypeNode;
819819
}
820820
interface IndexedAccessTypeNode extends TypeNode {
@@ -2286,6 +2286,7 @@ declare namespace ts {
22862286
interface TupleType extends GenericType {
22872287
minLength: number;
22882288
hasRestElement: boolean;
2289+
readonly: boolean;
22892290
associatedNames?: __String[];
22902291
}
22912292
interface TupleTypeReference extends TypeReference {
@@ -3759,7 +3760,7 @@ declare namespace ts {
37593760
function updateParenthesizedType(node: ParenthesizedTypeNode, type: TypeNode): ParenthesizedTypeNode;
37603761
function createThisTypeNode(): ThisTypeNode;
37613762
function createTypeOperatorNode(type: TypeNode): TypeOperatorNode;
3762-
function createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword, type: TypeNode): TypeOperatorNode;
3763+
function createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword, type: TypeNode): TypeOperatorNode;
37633764
function updateTypeOperatorNode(node: TypeOperatorNode, type: TypeNode): TypeOperatorNode;
37643765
function createIndexedAccessTypeNode(objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode;
37653766
function updateIndexedAccessTypeNode(node: IndexedAccessTypeNode, objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode;

tests/baselines/reference/arrayFind.types

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,15 @@ const foundNumber: number | undefined = arrayOfStringsNumbersAndBooleans.find(is
3030
>isNumber : (x: any) => x is number
3131

3232
const readonlyArrayOfStringsNumbersAndBooleans = arrayOfStringsNumbersAndBooleans as ReadonlyArray<string | number | boolean>;
33-
>readonlyArrayOfStringsNumbersAndBooleans : ReadonlyArray<string | number | boolean>
34-
>arrayOfStringsNumbersAndBooleans as ReadonlyArray<string | number | boolean> : ReadonlyArray<string | number | boolean>
33+
>readonlyArrayOfStringsNumbersAndBooleans : readonly (string | number | boolean)[]
34+
>arrayOfStringsNumbersAndBooleans as ReadonlyArray<string | number | boolean> : readonly (string | number | boolean)[]
3535
>arrayOfStringsNumbersAndBooleans : (string | number | boolean)[]
3636

3737
const readonlyFoundNumber: number | undefined = readonlyArrayOfStringsNumbersAndBooleans.find(isNumber);
3838
>readonlyFoundNumber : number
3939
>readonlyArrayOfStringsNumbersAndBooleans.find(isNumber) : number
40-
>readonlyArrayOfStringsNumbersAndBooleans.find : { <S extends string | number | boolean>(predicate: (this: void, value: string | number | boolean, index: number, obj: ReadonlyArray<string | number | boolean>) => value is S, thisArg?: any): S; (predicate: (value: string | number | boolean, index: number, obj: ReadonlyArray<string | number | boolean>) => boolean, thisArg?: any): string | number | boolean; }
41-
>readonlyArrayOfStringsNumbersAndBooleans : ReadonlyArray<string | number | boolean>
42-
>find : { <S extends string | number | boolean>(predicate: (this: void, value: string | number | boolean, index: number, obj: ReadonlyArray<string | number | boolean>) => value is S, thisArg?: any): S; (predicate: (value: string | number | boolean, index: number, obj: ReadonlyArray<string | number | boolean>) => boolean, thisArg?: any): string | number | boolean; }
40+
>readonlyArrayOfStringsNumbersAndBooleans.find : { <S extends string | number | boolean>(predicate: (this: void, value: string | number | boolean, index: number, obj: readonly (string | number | boolean)[]) => value is S, thisArg?: any): S; (predicate: (value: string | number | boolean, index: number, obj: readonly (string | number | boolean)[]) => boolean, thisArg?: any): string | number | boolean; }
41+
>readonlyArrayOfStringsNumbersAndBooleans : readonly (string | number | boolean)[]
42+
>find : { <S extends string | number | boolean>(predicate: (this: void, value: string | number | boolean, index: number, obj: readonly (string | number | boolean)[]) => value is S, thisArg?: any): S; (predicate: (value: string | number | boolean, index: number, obj: readonly (string | number | boolean)[]) => boolean, thisArg?: any): string | number | boolean; }
4343
>isNumber : (x: any) => x is number
4444

tests/baselines/reference/arrayFlatMap.types

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,22 @@ const array: number[] = [];
44
>[] : undefined[]
55

66
const readonlyArray: ReadonlyArray<number> = [];
7-
>readonlyArray : ReadonlyArray<number>
7+
>readonlyArray : readonly number[]
88
>[] : undefined[]
99

1010
array.flatMap((): ReadonlyArray<number> => []); // ok
1111
>array.flatMap((): ReadonlyArray<number> => []) : number[]
12-
>array.flatMap : <U, This = undefined>(callback: (this: This, value: number, index: number, array: number[]) => U | ReadonlyArray<U>, thisArg?: This) => U[]
12+
>array.flatMap : <U, This = undefined>(callback: (this: This, value: number, index: number, array: number[]) => U | readonly U[], thisArg?: This) => U[]
1313
>array : number[]
14-
>flatMap : <U, This = undefined>(callback: (this: This, value: number, index: number, array: number[]) => U | ReadonlyArray<U>, thisArg?: This) => U[]
15-
>(): ReadonlyArray<number> => [] : () => ReadonlyArray<number>
14+
>flatMap : <U, This = undefined>(callback: (this: This, value: number, index: number, array: number[]) => U | readonly U[], thisArg?: This) => U[]
15+
>(): ReadonlyArray<number> => [] : () => readonly number[]
1616
>[] : undefined[]
1717

1818
readonlyArray.flatMap((): ReadonlyArray<number> => []); // ok
1919
>readonlyArray.flatMap((): ReadonlyArray<number> => []) : number[]
20-
>readonlyArray.flatMap : <U, This = undefined>(callback: (this: This, value: number, index: number, array: number[]) => U | ReadonlyArray<U>, thisArg?: This) => U[]
21-
>readonlyArray : ReadonlyArray<number>
22-
>flatMap : <U, This = undefined>(callback: (this: This, value: number, index: number, array: number[]) => U | ReadonlyArray<U>, thisArg?: This) => U[]
23-
>(): ReadonlyArray<number> => [] : () => ReadonlyArray<number>
20+
>readonlyArray.flatMap : <U, This = undefined>(callback: (this: This, value: number, index: number, array: number[]) => U | readonly U[], thisArg?: This) => U[]
21+
>readonlyArray : readonly number[]
22+
>flatMap : <U, This = undefined>(callback: (this: This, value: number, index: number, array: number[]) => U | readonly U[], thisArg?: This) => U[]
23+
>(): ReadonlyArray<number> => [] : () => readonly number[]
2424
>[] : undefined[]
2525

0 commit comments

Comments
 (0)