Closed
Description
TypeScript Version: 3.0.1
Search Terms
- readonly
- literal type
- object prop
- inference
- type widening
Code
TypeScript currently behaves inconsistently when declaring a readonly
object directly in a function call.
const readonlyNamedProp = <
T extends { hello: string }
>(input: Readonly<T>) => input
const readonlyObject = <
T extends {}
>(input: Readonly<T>) => input
Expected behavior
const a = readonlyNamedProp({ hello: 'World' })
type A = typeof a // { readonly hello: 'World' }
const b = readonlyObject({ hello: 'World' })
type B = typeof b // { readonly hello: 'World' }
Actual behavior
const a = readonlyNamedProp({ hello: 'World' })
type A = typeof a // { readonly hello: 'World' }
const b = readonlyObject({ hello: 'World' })
type B = typeof b // { readonly hello: string }
Example usage
I'm willing to use this on a Runtime Type Check library (still dirty code):
https://github.com/kube/structype
const Animal = Type({
kind: 'animal',
age: Number,
name: String
})
if (Animal.test(someObj)) {
someObj.kind // 'animal' at runtime, but string statically
}
Workaround is to wrap kind
in a function call, which adds unnecessary verbosity:
const Animal = Type({
kind: Type('animal'),
age: Number,
name: String
})
Related Issues
Metadata
Metadata
Assignees
Type
Projects
Milestone
Relationships
Development
No branches or pull requests
Activity
ahejlsberg commentedon Aug 9, 2018
This is working as intended. In
readonlyNamedProp
, the argument is contextually typed by{ hello: string }
(the constraint ofT
) which is taken as an indication that you want to infer a literal type for thehello
property (i.e. some type that is a subtype ofstring
). However, inreadonlyObject
there is no constraint and therefore no contextual type for thehello
property, and since we're inferring for a mutable location we widen type'World'
tostring
.kube commentedon Aug 9, 2018
Ok I understand in case
T extends {}
.But if
T extends { [key: string]: string }
, shouldn't thehello
prop type be narrowed to'World'
?Playground link
typescript-bot commentedon Dec 14, 2018
This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes.