Closed
Description
TypeScript Version: 3.9.2
Search Terms:
mapped type filter object properties never
Expected behavior:
The type
type FilteredKeys<T, U> = { [P in keyof T]: T[P] extends U ? P : never }[keyof T];
that allows to extract object properties by type should work everywhere.
Actual behavior:
type FilteredKeys<T, U> = { [P in keyof T]: T[P] extends U ? P : never }[keyof T];
only works externally of the declaring type
Related Issues:
#23199
Code
type FilteredKeys<T, U> = { [P in keyof T]: T[P] extends U ? P : never }[keyof T];
type FooItem<T> = T extends number ? { value: T } : undefined;
type FooMap<T> = {
// [key in keyof T]: FooItem<T[key]> // <-- This works
[key in FilteredKeys<T, number>]: FooItem<T[key]> // <-- This doesn't work
}
class Bar {
a = 1;
b = 2;
c = '';
doSomething() {
const fooMap: FooMap<this> = undefined!; // Omitted...
const a = fooMap.a.value; // <-- No error expected
const c = fooMap.c.value; // <-- Error expected
}
}
const fooMap2: FooMap<Bar> = undefined!; // Omitted...
const a = fooMap2.a.value; // <-- No error expected
const c = fooMap2.c.value; // <-- Error expected
Output
"use strict";
class Bar {
constructor() {
this.a = 1;
this.b = 2;
this.c = '';
}
doSomething() {
const fooMap = undefined; // Omitted...
const a = fooMap.a.value; // <-- No error expected
const c = fooMap.c.value; // <-- Error expected
}
}
const fooMap2 = undefined; // Omitted...
const a = fooMap2.a.value; // <-- No error expected
const c = fooMap2.c.value; // <-- Error expected
Compiler Options
{
"compilerOptions": {
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictPropertyInitialization": true,
"strictBindCallApply": true,
"noImplicitThis": true,
"noImplicitReturns": true,
"useDefineForClassFields": false,
"alwaysStrict": true,
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"downlevelIteration": false,
"noEmitHelpers": false,
"noLib": false,
"noStrictGenericChecks": false,
"noUnusedLocals": false,
"noUnusedParameters": false,
"esModuleInterop": true,
"preserveConstEnums": false,
"removeComments": false,
"skipLibCheck": false,
"checkJs": false,
"allowJs": false,
"declaration": true,
"experimentalDecorators": false,
"emitDecoratorMetadata": false,
"target": "ES2017",
"module": "ESNext"
}
}
Playground Link: Provided