Typescript: Error: Type cannot be used to index type after two indexes

Created on 8 Feb 2018  ยท  11Comments  ยท  Source: microsoft/TypeScript


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

Bug

Most helpful comment

Actually, it's really weird! I'm getting type errors, but TS is getting the derived type right anyway!

All 11 comments

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>' is not assignable to type 'SpriteEventDispatcher Type 'AMEvent' is not assignable to type 'AMEvent node_modules/@amcharts/amcharts4/.internal/charts/types/XYChart.d.ts(264,33): error TS2344: Type 'this["_yAxisRendererType"]' does not satisfy the constraint 'AxisRenderer'.
Type 'AxisRendererY' is not assignable to type 'AxisRenderer'.
Types of property 'events' are incompatible.
Type 'SpriteEventDispatcher>' is not assignable to type 'SpriteEventDispatcher Type 'AMEvent' is not assignable to type 'AMEvent node_modules/@amcharts/amcharts4/.internal/charts/types/XYChart.d.ts(503,31): error TS2344: Type 'this["_xAxisRendererType"]' does not satisfy the constraint 'AxisRenderer'.
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'.

Was this page helpful?
0 / 5 - 0 ratings