TypeScript Version: 2.7.1, 2.8.0-dev.20180208
Search Terms:
Type cannot be used to index type
Code
interface IExample {
foo: {
bar: {
baz: number;
}
}
}
type F = <
name extends keyof IExample,
val extends keyof IExample[name]
>() => IExample[name][val]['baz']; // โ Type '"baz"' cannot be used to index type 'IExample[name][val]'.
Expected behavior:
In version 2.7.0-dev.20171115 this code was checking without errors.
Actual behavior:
Now in throws error: Type '"baz"' cannot be used to index type 'IExample[name][val]'.
Playground Link:
https://www.typescriptlang.org/play/index.html#src=interface%20IExample%20%7B%0D%0A%20%20%20%20foo%3A%20%7B%0D%0A%20%20%20%20%20%20%20%20bar%3A%20%7B%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20baz%3A%20number%3B%0D%0A%20%20%20%20%20%20%20%20%7D%0D%0A%20%20%20%20%7D%0D%0A%7D%0D%0A%0D%0Atype%20F%20%3D%20%3C%0D%0A%20%20%20%20name%20extends%20keyof%20IExample%2C%0D%0A%20%20%20%20val%20extends%20keyof%20IExample%5Bname%5D%0D%0A%3E()%20%3D%3E%20IExample%5Bname%5D%5Bval%5D%5B'baz'%5D%3B
Likely related to #21368
@sandersn can you take a look.
The nut of the problem is that the base constraint of U extends keyof IExample[T]
is string
, even though we would like it be "bar"
. This means that IExample[T][U]
doesn't have a constraint, and therefore can't be indexed by anything except keyof IExample[T][U]
, which "baz" is not.
I think it would be possible to fix this case by changing the rule for keyof types in computeBaseConstraint
to return getIndexType(getBaseConstraint(t.type))
instead of just return stringType
. I'll try it when I have time to see if it works.
Here's the change I made. It re-broke #15371, so I'm not sure it's the right change. I'll discuss with @ahejlsberg tomrrow.
if (t.flags & TypeFlags.Index) {
- return stringType;
+ const baseType = getBaseConstraint((t as IndexType).type);
+ const baseIndex = baseType ? getIndexType(baseType) : undefined;
+ return baseIndex && baseIndex !== unknownType ? getBaseConstraint(baseIndex) : undefined;
}
@sandersn hello, maybe there is any news?
This is a 2.8 upgrade blocker for me @DanielRosenwasser
Actually, it's really weird! I'm getting type errors, but TS is getting the derived type right anyway!
Is there any chance to get it fixed? I've got it working in my case, but only with strictNullChecks: false. We absolutely love strictNullChecks, so waiting for the fix)
So I have this piece of code:
type D<T> = {
[propertyName: string]: keyof T;
}
const f = <A, B, C extends D<B>>(
a: A, b: B, c: C,
): (
A & {
[K in keyof C]: B[C[K]] // this line
}
) => void 0 as any;
const result = f({
abc: 1,
}, {
def: true
}, {
ghi: 'def'
});
In TS 3.0.3 result.ghi
is correctly inferred as boolean
and no errors are displayed.
In TS 3.1.1 result.ghi
is (again) correctly inferred as boolean
, but in highlighted line it says Type 'C[K]' cannot be used to index type 'B'.
I'd greatly appreciate any help.
ERROR in node_modules/@amcharts/amcharts4/.internal/charts/types/XYChart.d.ts(258,33): error TS2344: Type 'this["_xAxisRendererType"]' does not satisfy the constraint 'AxisRenderer'.
Type 'AxisRendererX' is not assignable to type 'AxisRenderer'.
Types of property 'events' are incompatible.
Type 'SpriteEventDispatcher
Type 'AxisRendererY' is not assignable to type 'AxisRenderer'.
Types of property 'events' are incompatible.
Type 'SpriteEventDispatcher
node_modules/@amcharts/amcharts4/.internal/charts/types/XYChart.d.ts(513,31): error TS2344: Type 'this["_yAxisRendererType"]' does not satisfy the constraint 'AxisRenderer'.
node_modules/@amcharts/amcharts4/.internal/core/utils/Object.d.ts(60,117): error TS2536: Type 'Key' cannot be used to index type 'Object'.
node_modules/@amcharts/amcharts4/.internal/core/utils/Object.d.ts(67,109): error TS2536: Type 'Key' cannot be used to index type 'Object'.
node_modules/@amcharts/amcharts4/.internal/core/utils/Object.d.ts(76,116): error TS2536: Type 'Key' cannot be used to index type 'Object'.
node_modules/@amcharts/amcharts4/.internal/core/utils/Type.d.ts(25,32): error TS2304: Cannot find name 'Extract'.
Please.... Help Me...
Maybe related:
function getValues<T, K extends readonly (keyof T)[]>(object: T, keys: K): { [P in keyof K]: T[K[P]] } {
return keys.map(key => object[key]) as any
}
This shows the error: Type 'K[P]' cannot be used to index type 'T'.
Most helpful comment
Actually, it's really weird! I'm getting type errors, but TS is getting the derived type right anyway!