microsoft / TypeScript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
https://www.typescriptlang.org
Apache License 2.0
100.69k stars 12.44k forks source link

String literals doesn't work with object childs #16894

Closed fathyb closed 7 years ago

fathyb commented 7 years ago

TypeScript Version: 2.3.4

Code

const obj = {
    type: 'literal'
}
const type = 'literal'
const type2 = obj.type
const type3 = obj.type as 'literal'

// error: Argument of type 'string' is not assignable to parameter of type '"literal"'
void function(arg: 'literal') {}(obj.type) 

// error: Argument of type 'string' is not assignable to parameter of type '"literal"'
void function(arg: 'literal') {}(type2)

// works
void function(arg: 'literal') {}(type)

// works
void function(arg: 'literal') {}(type2 as 'literal')

// works
void function(arg: 'literal') {}(type3)

Expected behavior: It should accept string literals from objects

Actual behavior: We need to manually cast the variable to the literal type

rbuckton commented 7 years ago

This is intended behavior as we widen 'literal' to string in an object literal with no contextual type.

If you instead were to write:

const obj: { type: 'literal' } = { type: 'literal' };
const type2 = obj.type;

Then you would see the behavior you anticipate. We do not infer 'literal' for obj.type in this case is it would break many other use cases of const obj = { x: 'a' }; obj.x = 'b';.