镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

Literal type not inferred correctly when using generics #10685

Description

Version 2.0.2

type A = 'a'
const z: A[] = ['a']; // fine as expected

// how come 'a' cannot be inferred as type `A`?
const x: A[] = Array.from(['a'])  // Error: Type 'string' not assignable to 'a'

// my workaround (without creating a variable):
const y: A[] = Array.from([_.identity<A>('a')])

I think this may be related to #10676

Activity

  1. mhegazy commented on Sep 2, 2016

    @mhegazy
    Contributor

    The main problem is that literal types are not inferred unless there is a contextual type. and for generic types, return types are not an inference position. so the A[] in const x: A[] = Array.from(['a']) does not impact how T is inferred for Array.from call. and thus "a" is always inferred as string.

    The rational here is that literal types were added later on, and inferring them always by default would be a breaking change to code written before TS 1.8. e.g.:

    let x = `a`;
    x = `b` // Error x is `a`.

    Now #10676 is trying to address that by inferring literals more often. but it will not address all cases, such as the one above. you can see the description Anders Hejlsberg (@ahejlsberg) provides in the PR:

    During type argument inference, literal types are widened to their base primitive type unless the target type parameter has a constraint that includes primitive or literal types.

    The rational here is that a literal type is not super useful by itself, if the target of the inference is not one itself. e.g. new Array('a'), most likely you do not want an array of a's, but rather a string array with one initial value.

    so to an extent this issue is really a design limitation. if we infer literal types all the time, this breaks existing code in a huge way.

    A better work around for this scenario is to explicitly specify the generic type argument for Array.from, e.g:

    const y = Array.from<A>(['a']);
  2. locked and limited conversation to collaborators on Jun 19, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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