diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 02ab562e00091..09a08aac2ad5b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13042,6 +13042,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const typeParameter = getTypeParameterFromMappedType(type); const constraintType = getConstraintTypeFromMappedType(type); const nameType = getNameTypeFromMappedType(type.target as MappedType || type); + const isFilteringMappedType = nameType && isTypeAssignableTo(nameType, typeParameter); const templateType = getTemplateTypeFromMappedType(type.target as MappedType || type); const modifiersType = getApparentType(getModifiersTypeFromMappedType(type)); // The 'T' in 'keyof T' const templateModifiers = getMappedTypeModifiers(type); @@ -13088,9 +13089,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { prop.links.keyType = keyType; if (modifiersProp) { prop.links.syntheticOrigin = modifiersProp; - // If the mapped type has an `as XXX` clause, the property name likely won't match the declaration name and - // multiple properties may map to the same name. Thus, we attach no declarations to the symbol. - prop.declarations = nameType ? undefined : modifiersProp.declarations; + prop.declarations = !nameType || isFilteringMappedType ? modifiersProp.declarations : undefined; } members.set(propName, prop); } diff --git a/tests/baselines/reference/findAllReferencesFilteringMappedTypeProperty.baseline.jsonc b/tests/baselines/reference/findAllReferencesFilteringMappedTypeProperty.baseline.jsonc new file mode 100644 index 0000000000000..8453aea8c8330 --- /dev/null +++ b/tests/baselines/reference/findAllReferencesFilteringMappedTypeProperty.baseline.jsonc @@ -0,0 +1,284 @@ +// === /tests/cases/fourslash/findAllReferencesFilteringMappedTypeProperty.ts === +// const obj = { /*FIND ALL REFS*/[|a|]: 1, b: 2 }; +// const filtered: { [P in keyof typeof obj as P extends 'b' ? never : P]: 0; } = { [|a|]: 0 }; +// filtered.[|a|]; + +[ + { + "definition": { + "containerKind": "", + "containerName": "", + "fileName": "/tests/cases/fourslash/findAllReferencesFilteringMappedTypeProperty.ts", + "kind": "property", + "name": "(property) a: number", + "textSpan": { + "start": 14, + "length": 1 + }, + "displayParts": [ + { + "text": "(", + "kind": "punctuation" + }, + { + "text": "property", + "kind": "text" + }, + { + "text": ")", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "a", + "kind": "propertyName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "number", + "kind": "keyword" + } + ], + "contextSpan": { + "start": 14, + "length": 4 + } + }, + "references": [ + { + "textSpan": { + "start": 14, + "length": 1 + }, + "fileName": "/tests/cases/fourslash/findAllReferencesFilteringMappedTypeProperty.ts", + "contextSpan": { + "start": 14, + "length": 4 + }, + "isWriteAccess": true, + "isDefinition": true + }, + { + "textSpan": { + "start": 109, + "length": 1 + }, + "fileName": "/tests/cases/fourslash/findAllReferencesFilteringMappedTypeProperty.ts", + "contextSpan": { + "start": 109, + "length": 4 + }, + "isWriteAccess": true, + "isDefinition": false + }, + { + "textSpan": { + "start": 126, + "length": 1 + }, + "fileName": "/tests/cases/fourslash/findAllReferencesFilteringMappedTypeProperty.ts", + "isWriteAccess": false, + "isDefinition": false + } + ] + } +] + +// === /tests/cases/fourslash/findAllReferencesFilteringMappedTypeProperty.ts === +// const obj = { [|a|]: 1, b: 2 }; +// const filtered: { [P in keyof typeof obj as P extends 'b' ? never : P]: 0; } = { /*FIND ALL REFS*/[|a|]: 0 }; +// filtered.[|a|]; + +[ + { + "definition": { + "containerKind": "", + "containerName": "", + "fileName": "/tests/cases/fourslash/findAllReferencesFilteringMappedTypeProperty.ts", + "kind": "property", + "name": "(property) a: number", + "textSpan": { + "start": 14, + "length": 1 + }, + "displayParts": [ + { + "text": "(", + "kind": "punctuation" + }, + { + "text": "property", + "kind": "text" + }, + { + "text": ")", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "a", + "kind": "propertyName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "number", + "kind": "keyword" + } + ], + "contextSpan": { + "start": 14, + "length": 4 + } + }, + "references": [ + { + "textSpan": { + "start": 14, + "length": 1 + }, + "fileName": "/tests/cases/fourslash/findAllReferencesFilteringMappedTypeProperty.ts", + "contextSpan": { + "start": 14, + "length": 4 + }, + "isWriteAccess": true, + "isDefinition": false + }, + { + "textSpan": { + "start": 109, + "length": 1 + }, + "fileName": "/tests/cases/fourslash/findAllReferencesFilteringMappedTypeProperty.ts", + "contextSpan": { + "start": 109, + "length": 4 + }, + "isWriteAccess": true, + "isDefinition": true + }, + { + "textSpan": { + "start": 126, + "length": 1 + }, + "fileName": "/tests/cases/fourslash/findAllReferencesFilteringMappedTypeProperty.ts", + "isWriteAccess": false, + "isDefinition": false + } + ] + } +] + +// === /tests/cases/fourslash/findAllReferencesFilteringMappedTypeProperty.ts === +// const obj = { [|a|]: 1, b: 2 }; +// const filtered: { [P in keyof typeof obj as P extends 'b' ? never : P]: 0; } = { [|a|]: 0 }; +// filtered./*FIND ALL REFS*/[|a|]; + +[ + { + "definition": { + "containerKind": "", + "containerName": "", + "fileName": "/tests/cases/fourslash/findAllReferencesFilteringMappedTypeProperty.ts", + "kind": "property", + "name": "(property) a: number", + "textSpan": { + "start": 14, + "length": 1 + }, + "displayParts": [ + { + "text": "(", + "kind": "punctuation" + }, + { + "text": "property", + "kind": "text" + }, + { + "text": ")", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "a", + "kind": "propertyName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "number", + "kind": "keyword" + } + ], + "contextSpan": { + "start": 14, + "length": 4 + } + }, + "references": [ + { + "textSpan": { + "start": 14, + "length": 1 + }, + "fileName": "/tests/cases/fourslash/findAllReferencesFilteringMappedTypeProperty.ts", + "contextSpan": { + "start": 14, + "length": 4 + }, + "isWriteAccess": true + }, + { + "textSpan": { + "start": 109, + "length": 1 + }, + "fileName": "/tests/cases/fourslash/findAllReferencesFilteringMappedTypeProperty.ts", + "contextSpan": { + "start": 109, + "length": 4 + }, + "isWriteAccess": true + }, + { + "textSpan": { + "start": 126, + "length": 1 + }, + "fileName": "/tests/cases/fourslash/findAllReferencesFilteringMappedTypeProperty.ts", + "isWriteAccess": false + } + ] + } +] \ No newline at end of file diff --git a/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty.errors.txt b/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty.errors.txt index bbb76e12da4b2..8df22f7c578f9 100644 --- a/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty.errors.txt +++ b/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/mappedTypeWithAsClauseAndLateBoundProperty.ts(3,1): error TS2741: Property 'length' is missing in type '{ [x: number]: number; toString: () => string; toLocaleString: () => string; pop: () => number; push: (...items: number[]) => number; concat: { (...items: ConcatArray[]): number[]; (...items: (number | ConcatArray)[]): number[]; }; join: (separator?: string) => string; reverse: () => number[]; shift: () => number; slice: (start?: number, end?: number) => number[]; sort: (compareFn?: (a: number, b: number) => number) => number[]; splice: { (start: number, deleteCount?: number): number[]; (start: number, deleteCount: number, ...items: number[]): number[]; }; unshift: (...items: number[]) => number; indexOf: (searchElement: number, fromIndex?: number) => number; lastIndexOf: (searchElement: number, fromIndex?: number) => number; every: { (predicate: (value: number, index: number, array: number[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): boolean; }; some: (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any) => boolean; forEach: (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void; map: (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[]; filter: { (predicate: (value: number, index: number, array: number[]) => value is S, thisArg?: any): S[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): number[]; }; reduce: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; }; reduceRight: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; }; find: { (predicate: (value: number, index: number, obj: number[]) => value is S, thisArg?: any): S; (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any): number; }; findIndex: (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any) => number; fill: (value: number, start?: number, end?: number) => number[]; copyWithin: (target: number, start: number, end?: number) => number[]; entries: () => IterableIterator<[number, number]>; keys: () => IterableIterator; values: () => IterableIterator; includes: (searchElement: number, fromIndex?: number) => boolean; flatMap: (callback: (this: This, value: number, index: number, array: number[]) => U | readonly U[], thisArg?: This) => U[]; flat: (this: A, depth?: D) => FlatArray[]; [iterator]: () => IterableIterator; [unscopables]: () => { copyWithin: boolean; entries: boolean; fill: boolean; find: boolean; findIndex: boolean; keys: boolean; values: boolean; }; }' but required in type 'number[]'. +tests/cases/compiler/mappedTypeWithAsClauseAndLateBoundProperty.ts(3,1): error TS2741: Property 'length' is missing in type '{ [x: number]: number; toString: () => string; toLocaleString: () => string; pop: () => number; push: (...items: number[]) => number; concat: { (...items: ConcatArray[]): number[]; (...items: (number | ConcatArray)[]): number[]; }; join: (separator?: string) => string; reverse: () => number[]; shift: () => number; slice: (start?: number, end?: number) => number[]; sort: (compareFn?: (a: number, b: number) => number) => number[]; splice: { (start: number, deleteCount?: number): number[]; (start: number, deleteCount: number, ...items: number[]): number[]; }; unshift: (...items: number[]) => number; indexOf: (searchElement: number, fromIndex?: number) => number; lastIndexOf: (searchElement: number, fromIndex?: number) => number; every: { (predicate: (value: number, index: number, array: number[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): boolean; }; some: (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any) => boolean; forEach: (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void; map: (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[]; filter: { (predicate: (value: number, index: number, array: number[]) => value is S, thisArg?: any): S[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): number[]; }; reduce: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; }; reduceRight: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; }; find: { (predicate: (value: number, index: number, obj: number[]) => value is S, thisArg?: any): S; (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any): number; }; findIndex: (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any) => number; fill: (value: number, start?: number, end?: number) => number[]; copyWithin: (target: number, start: number, end?: number) => number[]; entries: () => IterableIterator<[number, number]>; keys: () => IterableIterator; values: () => IterableIterator; includes: (searchElement: number, fromIndex?: number) => boolean; flatMap: (callback: (this: This, value: number, index: number, array: number[]) => U | readonly U[], thisArg?: This) => U[]; flat: (this: A, depth?: D) => FlatArray[]; [Symbol.iterator]: () => IterableIterator; [Symbol.unscopables]: () => { copyWithin: boolean; entries: boolean; fill: boolean; find: boolean; findIndex: boolean; keys: boolean; values: boolean; }; }' but required in type 'number[]'. ==== tests/cases/compiler/mappedTypeWithAsClauseAndLateBoundProperty.ts (1 errors) ==== @@ -6,6 +6,6 @@ tests/cases/compiler/mappedTypeWithAsClauseAndLateBoundProperty.ts(3,1): error T declare let src2: { [K in keyof number[] as Exclude]: (number[])[K] }; tgt2 = src2; // Should error ~~~~ -!!! error TS2741: Property 'length' is missing in type '{ [x: number]: number; toString: () => string; toLocaleString: () => string; pop: () => number; push: (...items: number[]) => number; concat: { (...items: ConcatArray[]): number[]; (...items: (number | ConcatArray)[]): number[]; }; join: (separator?: string) => string; reverse: () => number[]; shift: () => number; slice: (start?: number, end?: number) => number[]; sort: (compareFn?: (a: number, b: number) => number) => number[]; splice: { (start: number, deleteCount?: number): number[]; (start: number, deleteCount: number, ...items: number[]): number[]; }; unshift: (...items: number[]) => number; indexOf: (searchElement: number, fromIndex?: number) => number; lastIndexOf: (searchElement: number, fromIndex?: number) => number; every: { (predicate: (value: number, index: number, array: number[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): boolean; }; some: (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any) => boolean; forEach: (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void; map: (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[]; filter: { (predicate: (value: number, index: number, array: number[]) => value is S, thisArg?: any): S[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): number[]; }; reduce: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; }; reduceRight: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; }; find: { (predicate: (value: number, index: number, obj: number[]) => value is S, thisArg?: any): S; (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any): number; }; findIndex: (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any) => number; fill: (value: number, start?: number, end?: number) => number[]; copyWithin: (target: number, start: number, end?: number) => number[]; entries: () => IterableIterator<[number, number]>; keys: () => IterableIterator; values: () => IterableIterator; includes: (searchElement: number, fromIndex?: number) => boolean; flatMap: (callback: (this: This, value: number, index: number, array: number[]) => U | readonly U[], thisArg?: This) => U[]; flat: (this: A, depth?: D) => FlatArray[]; [iterator]: () => IterableIterator; [unscopables]: () => { copyWithin: boolean; entries: boolean; fill: boolean; find: boolean; findIndex: boolean; keys: boolean; values: boolean; }; }' but required in type 'number[]'. +!!! error TS2741: Property 'length' is missing in type '{ [x: number]: number; toString: () => string; toLocaleString: () => string; pop: () => number; push: (...items: number[]) => number; concat: { (...items: ConcatArray[]): number[]; (...items: (number | ConcatArray)[]): number[]; }; join: (separator?: string) => string; reverse: () => number[]; shift: () => number; slice: (start?: number, end?: number) => number[]; sort: (compareFn?: (a: number, b: number) => number) => number[]; splice: { (start: number, deleteCount?: number): number[]; (start: number, deleteCount: number, ...items: number[]): number[]; }; unshift: (...items: number[]) => number; indexOf: (searchElement: number, fromIndex?: number) => number; lastIndexOf: (searchElement: number, fromIndex?: number) => number; every: { (predicate: (value: number, index: number, array: number[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): boolean; }; some: (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any) => boolean; forEach: (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void; map: (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[]; filter: { (predicate: (value: number, index: number, array: number[]) => value is S, thisArg?: any): S[]; (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): number[]; }; reduce: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; }; reduceRight: { (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; (callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: number[]) => U, initialValue: U): U; }; find: { (predicate: (value: number, index: number, obj: number[]) => value is S, thisArg?: any): S; (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any): number; }; findIndex: (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any) => number; fill: (value: number, start?: number, end?: number) => number[]; copyWithin: (target: number, start: number, end?: number) => number[]; entries: () => IterableIterator<[number, number]>; keys: () => IterableIterator; values: () => IterableIterator; includes: (searchElement: number, fromIndex?: number) => boolean; flatMap: (callback: (this: This, value: number, index: number, array: number[]) => U | readonly U[], thisArg?: This) => U[]; flat: (this: A, depth?: D) => FlatArray[]; [Symbol.iterator]: () => IterableIterator; [Symbol.unscopables]: () => { copyWithin: boolean; entries: boolean; fill: boolean; find: boolean; findIndex: boolean; keys: boolean; values: boolean; }; }' but required in type 'number[]'. !!! related TS2728 /.ts/lib.es5.d.ts:--:--: 'length' is declared here. \ No newline at end of file diff --git a/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty2.errors.txt b/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty2.errors.txt deleted file mode 100644 index 087365b20981f..0000000000000 --- a/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty2.errors.txt +++ /dev/null @@ -1,11 +0,0 @@ -tests/cases/compiler/mappedTypeWithAsClauseAndLateBoundProperty2.ts(1,14): error TS4118: The type of this node cannot be serialized because its property '[iterator]' cannot be serialized. -tests/cases/compiler/mappedTypeWithAsClauseAndLateBoundProperty2.ts(1,14): error TS4118: The type of this node cannot be serialized because its property '[unscopables]' cannot be serialized. - - -==== tests/cases/compiler/mappedTypeWithAsClauseAndLateBoundProperty2.ts (2 errors) ==== - export const thing = (null as any as { [K in keyof number[] as Exclude]: (number[])[K] }); - ~~~~~ -!!! error TS4118: The type of this node cannot be serialized because its property '[iterator]' cannot be serialized. - ~~~~~ -!!! error TS4118: The type of this node cannot be serialized because its property '[unscopables]' cannot be serialized. - \ No newline at end of file diff --git a/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty2.js b/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty2.js index 82ced9d506184..db487cd917b84 100644 --- a/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty2.js +++ b/tests/baselines/reference/mappedTypeWithAsClauseAndLateBoundProperty2.js @@ -4,3 +4,152 @@ export const thing = (null as any as { [K in keyof number[] as Exclude string; + toLocaleString: () => string; + pop: () => number; + push: (...items: number[]) => number; + concat: { + (...items: ConcatArray[]): number[]; + (...items: (number | ConcatArray)[]): number[]; + }; + join: (separator?: string) => string; + reverse: () => number[]; + shift: () => number; + slice: (start?: number, end?: number) => number[]; + sort: (compareFn?: (a: number, b: number) => number) => number[]; + splice: { + (start: number, deleteCount?: number): number[]; + (start: number, deleteCount: number, ...items: number[]): number[]; + }; + unshift: (...items: number[]) => number; + indexOf: (searchElement: number, fromIndex?: number) => number; + lastIndexOf: (searchElement: number, fromIndex?: number) => number; + every: { + (predicate: (value: number, index: number, array: number[]) => value is S, thisArg?: any): this is S[]; + (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): boolean; + }; + some: (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any) => boolean; + forEach: (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void; + map: (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[]; + filter: { + (predicate: (value: number, index: number, array: number[]) => value is S_1, thisArg?: any): S_1[]; + (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): number[]; + }; + reduce: { + (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; + (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; + (callbackfn: (previousValue: U_1, currentValue: number, currentIndex: number, array: number[]) => U_1, initialValue: U_1): U_1; + }; + reduceRight: { + (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; + (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; + (callbackfn: (previousValue: U_2, currentValue: number, currentIndex: number, array: number[]) => U_2, initialValue: U_2): U_2; + }; + find: { + (predicate: (value: number, index: number, obj: number[]) => value is S_2, thisArg?: any): S_2; + (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any): number; + }; + findIndex: (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any) => number; + fill: (value: number, start?: number, end?: number) => number[]; + copyWithin: (target: number, start: number, end?: number) => number[]; + entries: () => IterableIterator<[number, number]>; + keys: () => IterableIterator; + values: () => IterableIterator; + includes: (searchElement: number, fromIndex?: number) => boolean; + flatMap: (callback: (this: This, value: number, index: number, array: number[]) => U_3 | readonly U_3[], thisArg?: This) => U_3[]; + flat: (this: A, depth?: D) => FlatArray[]; + [Symbol.iterator]: () => IterableIterator; + [Symbol.unscopables]: () => { + copyWithin: boolean; + entries: boolean; + fill: boolean; + find: boolean; + findIndex: boolean; + keys: boolean; + values: boolean; + }; +}; + + +//// [DtsFileErrors] + + +tests/cases/compiler/mappedTypeWithAsClauseAndLateBoundProperty2.d.ts(24,118): error TS2526: A 'this' type is available only in a non-static member of a class or interface. + + +==== tests/cases/compiler/mappedTypeWithAsClauseAndLateBoundProperty2.d.ts (1 errors) ==== + export declare const thing: { + [x: number]: number; + toString: () => string; + toLocaleString: () => string; + pop: () => number; + push: (...items: number[]) => number; + concat: { + (...items: ConcatArray[]): number[]; + (...items: (number | ConcatArray)[]): number[]; + }; + join: (separator?: string) => string; + reverse: () => number[]; + shift: () => number; + slice: (start?: number, end?: number) => number[]; + sort: (compareFn?: (a: number, b: number) => number) => number[]; + splice: { + (start: number, deleteCount?: number): number[]; + (start: number, deleteCount: number, ...items: number[]): number[]; + }; + unshift: (...items: number[]) => number; + indexOf: (searchElement: number, fromIndex?: number) => number; + lastIndexOf: (searchElement: number, fromIndex?: number) => number; + every: { + (predicate: (value: number, index: number, array: number[]) => value is S, thisArg?: any): this is S[]; + ~~~~ +!!! error TS2526: A 'this' type is available only in a non-static member of a class or interface. + (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): boolean; + }; + some: (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any) => boolean; + forEach: (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void; + map: (callbackfn: (value: number, index: number, array: number[]) => U, thisArg?: any) => U[]; + filter: { + (predicate: (value: number, index: number, array: number[]) => value is S_1, thisArg?: any): S_1[]; + (predicate: (value: number, index: number, array: number[]) => unknown, thisArg?: any): number[]; + }; + reduce: { + (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; + (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; + (callbackfn: (previousValue: U_1, currentValue: number, currentIndex: number, array: number[]) => U_1, initialValue: U_1): U_1; + }; + reduceRight: { + (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number): number; + (callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: number[]) => number, initialValue: number): number; + (callbackfn: (previousValue: U_2, currentValue: number, currentIndex: number, array: number[]) => U_2, initialValue: U_2): U_2; + }; + find: { + (predicate: (value: number, index: number, obj: number[]) => value is S_2, thisArg?: any): S_2; + (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any): number; + }; + findIndex: (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any) => number; + fill: (value: number, start?: number, end?: number) => number[]; + copyWithin: (target: number, start: number, end?: number) => number[]; + entries: () => IterableIterator<[number, number]>; + keys: () => IterableIterator; + values: () => IterableIterator; + includes: (searchElement: number, fromIndex?: number) => boolean; + flatMap: (callback: (this: This, value: number, index: number, array: number[]) => U_3 | readonly U_3[], thisArg?: This) => U_3[]; + flat: (this: A, depth?: D) => FlatArray[]; + [Symbol.iterator]: () => IterableIterator; + [Symbol.unscopables]: () => { + copyWithin: boolean; + entries: boolean; + fill: boolean; + find: boolean; + findIndex: boolean; + keys: boolean; + values: boolean; + }; + }; + \ No newline at end of file diff --git a/tests/cases/fourslash/findAllReferencesFilteringMappedTypeProperty.ts b/tests/cases/fourslash/findAllReferencesFilteringMappedTypeProperty.ts new file mode 100644 index 0000000000000..e77dee44cb7d4 --- /dev/null +++ b/tests/cases/fourslash/findAllReferencesFilteringMappedTypeProperty.ts @@ -0,0 +1,7 @@ +/// + +////const obj = { /*1*/a: 1, b: 2 }; +////const filtered: { [P in keyof typeof obj as P extends 'b' ? never : P]: 0; } = { /*2*/a: 0 }; +////filtered./*3*/a; + +verify.baselineFindAllReferences('1', '2', '3'); diff --git a/tests/cases/fourslash/goToDefinition_filteringMappedType.ts b/tests/cases/fourslash/goToDefinition_filteringMappedType.ts new file mode 100644 index 0000000000000..56ffe4130d3cd --- /dev/null +++ b/tests/cases/fourslash/goToDefinition_filteringMappedType.ts @@ -0,0 +1,7 @@ +/// + +////const obj = { /*def*/a: 1, b: 2 }; +////const filtered: { [P in keyof typeof obj as P extends 'b' ? never : P]: 0; } = { a: 0 }; +////filtered.[|/*ref*/a|]; + +verify.goToDefinition("ref", "def");