Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
runspired opened this issue Jun 17, 2021 · 1 comment
Closed

Comments

@runspired
Copy link

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.

@runspired
Copy link
Author

Closing because what I was missing is that mapped types eagerly resolve their type, so string here is correct and is also not serving as "the union of all strings". If a union could be constructed this pattern will work, unfortunately in my case a union cannot be constructed, and the solution I need is #26797

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant