Skip to content

Numeric template type can't be used to index tuple in mapped type (despite actually working anyway) #48739

Closed as not planned
@Jamesernator

Description

@Jamesernator

Bug Report

🔎 Search Terms

numeric string, number template, tuple

🕗 Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about template type

Note

This is a followup to another issue I raised where similar issues arose, however here the exact cause is different and more obviously a bug rather than intended behaviour.

This might still be a design limitation, but it's unclear to me how, without this, one can map a tuple type to something with a generic constraint.

⏯ Playground Link

Playground link with relevant code

💻 Code

class ValType {
    #isValType = true;
}

class I32 extends ValType {
    #isI32 = true;
}

class Externref extends ValType {
    #isExternref = true;
}

class Local<T extends ValType> {
    readonly #type: T;

    constructor(type: T) {
        this.#type = type;
    }

    get type(): T {
        return this.#type;
    }
}

type LocalsFor<Type extends ReadonlyArray<ValType>> = {
    [K in keyof Type]: K extends number ? Local<Type[K]>
        // Type 'Type[K]' does not satisfy the constraint 'ValType'.
        //   Type 'Type[`${number}` & string]' is not assignable to type 'ValType'.(2344)
        : K extends `${ number }` ? Local<Type[K]>
        : Type[K]
};

// This is still the correct type, despite the above error, so clearly
// the keys "0" and "1" are successfully interpreted as `${ number }` in
// the conditional type
const locals: LocalsFor<[I32, Externref]> = [
    new Local(new I32()),
    new Local(new Externref()),
];

🙁 Actual behavior

It produces an error, despite the fact K extends `${ number }` should be treated as a tuple key. (As per the other issue I raised numbers can't be used to index tuples, so a numeric string is the only way to distinguish tuple entry keys from methods for mapping tuple types).

The final bit of code, shows that the constraint does work, however it's not treated as a valid key for ReadonlyArray<ValType> despite subtypes being potentially tuples.

Note that because of the type constraint, mapped tuple types do not work.

🙂 Expected behavior

This should not have an error, as it otherwise works and the constraint should filter the tuple member keys (and not the methods).

Metadata

Metadata

Assignees

No one assigned

    Labels

    UnactionableThere isn't something we can do with this issue

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions