Skip to content

Conditionals checks of the key used with Mapped Types don't work as expectedΒ #44625

Closed
@runspired

Description

@runspired

Bug Report

πŸ”Ž Search Terms

Mapped Types, Conditionals, Template Types, Index Types, Index Signature

πŸ•— Version & Regression Information

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

⏯ Playground Link

Playground link with relevant code

πŸ’» Code

Below we use the following as a placeholder type. The specific "value" type in these examples is immaterial.

type AValue = { hello: 'world' };

Example 1

In the below example, t0 will be of type string because T will have type string instead of the narrower string literal type you might expect. This is the result with or without as T in the index signature but is even more surprising given the cast.

This example is important only in that it establishes how T has type string, the ramifications of this are more clear in the examples following.

type MappedTypeWithKeyReturn = {
  [T in string as T]: T;
}
// type should be 'aKey' not string 
type t0 = MappedTypeWithKeyReturn['aKey'];

Example 2

A slightly more complex example showing we cant use extends in the value portion as might be expected. This example fails even if we do T in string as T for the index signature, and fails even when V is not a generic but statically known.

type MappedTypeWithConditionalValue<V extends string, R> = {
  [T in string]: T extends V ? R : unknown;
}

// type should be { hello: 'world' } not unknown
type t1 = MappedTypeWithConditionalValue<'aKey', AValue>['aKey'];

Example 3

This example shows we cannot use an extends check properly within the index signature for any V that
is not simply string.

type MappedTypeWithConstraint<V extends string, R> = {
  [T in string as T extends V ? T : never]: R;
}

// type should be { hello: 'world' } not an error
type t2 = MappedTypeWithConstraint<'aKey', AValue>['aKey'];

Example 4

A more complex example showing that the above issues prevent using a template string check
with a mapped type, via either index or value approach.

type IndexStr = `com.some.thing.${string}`;

// type should be { hello: 'world' } not unknown
type t3 = MappedTypeWithConditionalValue<IndexStr, AValue>['com.some.thing.foo'];

// type should be { hello: 'world' } not an error
type t4 = MappedTypeWithConstraint<IndexStr, AValue>['com.some.thing.foo'];

πŸ™ Actual behavior

Was not able utilize a conditional type within either the index signature or the value of a mapped type.

πŸ™‚ Expected behavior

Should be able utilize a conditional type within either the index signature or the value of a mapped type.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions