Skip to content

Indexing a mapped type with a nested key from the original type emits compiler errors #43982

Closed
@00benallen

Description

@00benallen

Bug Report / Feature Request

When indexing a mapped type that is meant to have the same keys as an original type, the compiler emits errors when using a generic type which is a key of the original type:

Playground Link with Demonstration

https://www.typescriptlang.org/play?module=5&strict=true&ts=4.0.5&ssl=1&ssc=1&pln=43&pc=1#code/KYDwDg9gTgLgBASwHY2FAZgQwMbDgeSgQHNlMAbOAbwCg564woIwBGALmroZ4GcBXAEYAFZm068YRJMQA03HvQEixAJglTkxBXAC+8nkxbquihstEsAzBulydfIZbAAWW1p26aX0JFhwYAE8wPABpYED8dEISMkoAXjgAawiIdAIiUiQKAG4aX2h4IJC4ADlgSWAAE3DI6My4gDFoAB4AFThQVCQq3jhaqJisigA+OESUwLSM2OzyAG02gF0afPBCuGwIJEk4YmAYAGVNGUbmAFshuPG4FtDOkG7e-ojBhrnZMoenvvLKmte9VmFGaUDuIxGAApoMDyJwrh9khFOKFPkgKqgAYFOKUAJTw94UeahJbzUpLUwMKAHfhQJBwGHDBaTUno-61JZ5LxrPxFYJ4Q6Yc7AWq8dpjRK0HjExD0ybTZacKVmODE1SypFTdJtYlLJacJD8c6CNB5HhebkFfzFPAAWUwYBCVTOEEuhIScEFwtFLQRozyNAA9AAqYN0YNwNoACwQfWFMCjECqcF4if45GTAHdoElPpg+vdMD0vphqXt+KWi6hqgEIHATXAAG4UBDJyZ9aaCCAJmZMuBF5P2x3VF1u2HhuAT6N4TOYQIBKN4G19Ut4Xg0sCfBDwWOy5vkVu1zbbSRQfjYeBF2WSIu4BnpIdO0d+yiZmPYKNwKP575QTCMMQ0BgBAKgZKBEDjWNeC0fsAJYIDAgnKcYz6UAhTAcg8AoXg62zKAkj6BB0gASTgKptgAcngfh1zgNlMU1XhPgAKxo+BtjwTDG2AShpkmOBzgdMAYN3dBkGAAA6OB1S4niO3SfjBMdGDBGpTACKk8NAx5DYth2eB9iOE5iAAQR6UojRNKBn3dMyqkfGtEh0O5vmAHoC0BF9PlKVz3LKDFqgGIEmVBcEoQcBhGTiAlYU+CL6CUp8LhfTgHOdZL3TilVNRRNEAqxHEdHxVUX11Mklk+NKbNhMryQpeIxioOBA0DSN+TgCjSgozYiyQbt6zwGiaxgOtkCqUAAnaiivRFCIxRfEZdQo+K4GpGBaXpeYormeYWXmejAoiCqBKEkcMpqvaDqxPVmtatopq6nqkD6+AGyG5MRtlcaQEmkppqFWbAnm91FpJZbzVWGggA

Static Code Sample

export interface Original {
    prop1: {
        subProp1: string,
        subProp2: string
    },
    prop2: {
        subProp3: string,
        subProp4: string
    }
}

export type KeyOfOriginal = keyof Original;
export type NestedKeyOfOriginalFor<T extends KeyOfOriginal> = keyof Original[T]

export const getStringFromOriginal = <K extends KeyOfOriginal, N extends NestedKeyOfOriginalFor<K>>(original: Original, key: K, nestedKey: N): Original[K][N] {
    return original[key][nestedKey];
}

export type SameKeys<T> = {
    [K in keyof T]: {
        [K2 in keyof T[K]]: number;
    }
}

export type MappedFromOriginal = SameKeys<Original>;

/**
* This method should work, as K and N are guaranteed to be valid keys of both Original and MappedFromOriginal
*
 * The way the types are setup, it is invalid to construct an instance of MappedFromOriginal which has extra properties or is missing a property
*
 * This example also works if I don't use nested keys, just one level of key mapping is fine. 2 levels of key mapping breaks.
 */

export const getStringAndNumberFromOriginalAndMapped =
    <K extends KeyOfOriginal, N extends NestedKeyOfOriginalFor<K>>(
        original: Original,
        mappedFromOriginal: MappedFromOriginal,
        key: K, nestedKey: N
    ): [Original[K][N], MappedFromOriginal[K][N]] => { // Type 'N' cannot be used to index type 'SameKeys<Original>[K]'
        return [original[key][nestedKey], mappedFromOriginal[key][nestedKey]] // Type 'N' cannot be used to index type 'SameKeys<Original>[K]'
    }

Metadata

Metadata

Assignees

No one assigned

    Labels

    Design LimitationConstraints of the existing architecture prevent this from being fixed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions