Reputation: 13
interface IOptions {
foo: 'bar';
}
const example = (opts: IOptions) => console.log(opts);
const options = { foo: 'bar' };
example(options); // Argument of type '{ foo: string; }' is not assignable to parameter of type 'IOptions'. Types of property 'foo' are incompatible. Type 'string' is not assignable to type '"bar"'.
example({ foo: 'bar' }); // runs fine
As you can see I passed same exact object, but if I define it first it's doesn't work for some reason.
Upvotes: 1
Views: 130
Reputation: 37948
You've used string literal type for foo
property:
foo: 'bar';
String literal types allow you to specify the exact value a string must have
This means that foo
can hold only 'bar'
value (not any string
).
Type of options
is resolved to { foo: string }
because foo
is mutable. If you want to force typescript to infer literal type, you can use as const
assertion:
const options = { foo: 'bar' } as const; // type is { readonly foo: "bar"; }
example(options); // no error now
Another option is specifying the type explicitly:
const options: IOptions = { foo: 'bar' };
If you want to allow foo
to accept any string
, change the definition to:
interface IOptions {
foo: string;
}
Upvotes: 1
Reputation: 4330
You need to define the type of options. Because just by defining the const it is not guaranteed that your defined will continue to have the same signature, you can add or remove keys at any point of time as it is not explicitly defined with any type it can raise an error.
interface IOptions {
foo: 'bar';
}
const example = (opts: IOptions) => console.log(opts);
const options: IOptions = { foo: 'bar' }; // define type here
const options2 = { foo: 'bar' };
example(options);
example(options2 as IOptions) // If you are sure that options 2 is correct type
example({ foo: 'bar' });
Upvotes: 0