TypeScript Version: 2.4.1
Code
// @ts-check
import * as React from "react";
const styles = {
search: {
position: "relative",
}
}
const Foo = () => (
<div style={styles.search}></div>
);
Expected behavior:
Everything should be 馃憣
Actual behavior:
Getting a type error...
[js]
Type '{ style: { [x: string]: any; position: string; }; }' is not assignable to type 'DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>'.
Type '{ style: { [x: string]: any; position: string; }; }' is not assignable to type 'HTMLAttributes<HTMLDivElement>'.
Types of property 'style' are incompatible.
Type '{ [x: string]: any; position: string; }' is not assignable to type 'CSSProperties'.
[js]
Type '{ style: { [x: string]: any; position: string; }; }' is not assignable to type 'DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>'.
Type '{ style: { [x: string]: any; position: string; }; }' is not assignable to type 'HTMLAttributes<HTMLDivElement>'.
Types of property 'style' are incompatible.
Type '{ [x: string]: any; position: string; }' is not assignable to type 'CSSProperties'.
Types of property 'position' are incompatible.
Type 'string' is not assignable to type '"relative" | "initial" | "inherit" | "unset" | "static" | "absolute" | "fixed" | "sticky"'.
(property) search: {
[x: string]: any;
position: string;
}
This is just a case of the more general problem:
const x = { value: "lit" };
const y: { value: "lit" } = x; // Error
The problem is that since x has no type annotation, a new type is synthesized for it; and by default this type will use string instead of a string literal type.
This issue surfaces in TypeScript code as well and is unrelated to @ts-check.
The error stems from the fact that position is a mutable property of the styles local. because it is mutable, it is inferred as having type string instead of having a literal type.
See also #11465
This is not specific to @ts-check as @aluanhaddad noted. you can find similar discussion in https://github.com/Microsoft/TypeScript/issues/16389.
The recommendation here is to add a type annotation on your declaration to guide the compiler to inferring the literal types, e.g.:
/** @type {{search: React.CSSProperties}} */
const styles = {
search: {
position: "relative",
}
}
Ah, great, should I keep this open or close it then?
There are a few of elk of #16389 around. we have no plans on changing the design at this point. we already had multiple iterations on how literal types are inferred and the current design seems to be the best compromise we can reach.
Sounds good. Closing!
Most helpful comment
This is not specific to
@ts-checkas @aluanhaddad noted. you can find similar discussion in https://github.com/Microsoft/TypeScript/issues/16389.The recommendation here is to add a type annotation on your declaration to guide the compiler to inferring the literal types, e.g.: