Skip to content

Issues working with Generic Constraints #34567

Closed
@Dsan10s

Description

@Dsan10s

TypeScript Version: 3.6.4

Search Terms:
generic, generics, constraints

Context
Hello Typescript team!

I've been working on updating my team's typescript codebase from v 3.2.1 to v 3.6.4

I'm having some issues updating my codebase to support the breaking changes, and wanted to start a discussion to see if what I'm coming across is by design, and if so, what is the recommended solution for working through it.

Below I'll create a simplified example of the issue we're having, and I've verified that the issue only appears after and including Typescript 3.5. I believe the issue may be related to this

Code

interface StoreParams {
  key1: string;
  key2: number;
  key3: string[];
}

function get<Key extends keyof StoreParams>(key: Key): StoreParams[Key] | null {
  const key1Return: string = 'key1Return';
  const key2Return: number = 2;
  const key3Return: string[] = ['a', 'b', 'c'];

  if (key === 'key1') {
    return key1Return;
  }

  if (key === 'key2') {
    return key2Return;
  }

  if (key === 'key3') {
    return key3Return;
  }

  return null;
}

Expected behavior:
No compiler errors

Actual behavior:
The above code results in an error in each of the key return statements, respectively they are:

Type 'string' is not assignable to type 'StoreParams[Key] | null'.
Type 'number' is not assignable to type 'StoreParams[Key] | null'.
Type 'string[]' is not assignable to type 'StoreParams[Key]'.
  Type 'string[]' is not assignable to type 'never'.

It seems in each of the return statements, the return type is still StoreParams[Key] | null, where Key has not been filtered down after the if statement which normally acts as a type guard for key.

If I replace the generic Key with just keyof StoreParams, the type guards seem to work on key, but I've lost the benefit of the generic in that I'm still just returning StoreParams[keyof StoreParams], meaning in each of the return statements I can return string | number | string[] | null.

Playground Link: Link here

Related Issues:

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