Skip to content

Generics accept non-type as a type variable #27966

Closed
@mathiajusth

Description

@mathiajusth

TypeScript Version: 3.1.2

Expected behavior:
TS should not allow us to use a value instead of a type as argument to Generic (it is a type error)
(e.g - see code below - IType<E.a> should error. Only IType<E> is correct for E.a is not a type but a value of type E)

Actual behavior:
TS treats value of an enum like a type when fed to Generic. It results in type inference problems (see the example below)

Code

enum E {
	a = 'a',
	b = 'b',
}

interface IType<T> {
	type: T
}
 
interface IArrayA {
	listOfTypeA: Array<IType<E.a>>
}

interface IArrayB {
	listOfTypeB: Array<IType<E.b>>
}

const a: IArrayA = {
	listOfTypeA: [{type: E.a}],
}

const b: IArrayB = {
	listOfTypeB: a.listOfTypeA.map(() => ({type: E.b})), // ERROR: Type 'E' is not assignable to type 'E.b'.
}

Error explanation:
Ofc TS's type inference infers that {type: E.b} is of type {type: E} as it should. From that it infers b: {listOfTypeB: Array<{type: E}>}. But we wanted b: {listOfTypeB: Array<{type: E.b}>}.

Workaround: You can override TS's type system and tell it that E.b is of type E.b (although E.b is not a type...)
listOfTypeB: a.listOfTypeA.map(() => ({type: E.b as E.b})),

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions