I just upgraded from TypeScript 1.5 to the latest and I'm seeing an error in my code:
interface Options { /* ... others ... */ callbackOnLocationHash?: boolean; } function f(opts: Options) { /* ... */ } // Error: Object literal may only specify known properties, // and 'callbackOnLoactionHash'does not exist in type 'Options'. f( { callbackOnLoactionHash: false });
Code looks fine to me. What's wrong?
(Alternative universe version: I recognize the typo, and I really did mean to write that. What should I do to remove the error?)
Object literals are defined using the following syntax rules: A colon separates property name[1] from value. A comma separates each name-value pair from the next. A comma after the last name-value pair is optional.
Object Literal. In plain English, an object literal is a comma-separated list of name-value pairs inside of curly braces. Those values can be properties and functions. Here's a snippet of an object literal with one property and one function.
The object literal is a short form of creating an object. Define an object in the { } brackets with key:value pairs separated by a comma. The key would be the name of the property and the value will be a literal value or a function.
Object literals. An object literal is a list of zero or more pairs of property names and associated values of an object, enclosed in curly braces ( {} ).
As of TypeScript 1.6, properties in object literals that do not have a corresponding property in the type they're being assigned to are flagged as errors.
Usually this error means you have a bug (typically a typo) in your code, or in the definition file. The right fix in this case would be to fix the typo. In the question, the property callbackOnLoactionHash
is incorrect and should have been callbackOnLocationHash
(note the mis-spelling of "Location").
This change also required some updates in definition files, so you should get the latest version of the .d.ts for any libraries you're using.
Example:
interface TextOptions { alignment?: string; color?: string; padding?: number; } function drawText(opts: TextOptions) { ... } drawText({ align: 'center' }); // Error, no property 'align' in 'TextOptions'
There are a few cases where you may have intended to have extra properties in your object. Depending on what you're doing, there are several appropriate fixes
Sometimes you want to make sure a few things are present and of the correct type, but intend to have extra properties for whatever reason. Type assertions (<T>v
or v as T
) do not check for extra properties, so you can use them in place of a type annotation:
interface Options { x?: string; y?: number; } // Error, no property 'z' in 'Options' let q1: Options = { x: 'foo', y: 32, z: 100 }; // OK let q2 = { x: 'foo', y: 32, z: 100 } as Options; // Still an error (good): let q3 = { x: 100, y: 32, z: 100 } as Options;
Some APIs take an object and dynamically iterate over its keys, but have 'special' keys that need to be of a certain type. Adding a string indexer to the type will disable extra property checking
Before
interface Model { name: string; } function createModel(x: Model) { ... } // Error createModel({name: 'hello', length: 100});
After
interface Model { name: string; [others: string]: any; } function createModel(x: Model) { ... } // OK createModel({name: 'hello', length: 100});
interface Animal { move; } interface Dog extends Animal { woof; } interface Cat extends Animal { meow; } interface Horse extends Animal { neigh; } let x: Animal; if(...) { x = { move: 'doggy paddle', woof: 'bark' }; } else if(...) { x = { move: 'catwalk', meow: 'mrar' }; } else { x = { move: 'gallop', neigh: 'wilbur' }; }
Two good solutions come to mind here
Specify a closed set for x
// Removes all errors let x: Dog|Cat|Horse;
or Type assert each thing
// For each initialization x = { move: 'doggy paddle', woof: 'bark' } as Dog;
A clean solution to the "data model" problem using intersection types:
interface DataModelOptions { name?: string; id?: number; } interface UserProperties { [key: string]: any; } function createDataModel(model: DataModelOptions & UserProperties) { /* ... */ } // findDataModel can only look up by name or id function findDataModel(model: DataModelOptions) { /* ... */ } // OK createDataModel({name: 'my model', favoriteAnimal: 'cat' }); // Error, 'ID' is not correct (should be 'id') findDataModel({ ID: 32 });
See also https://github.com/Microsoft/TypeScript/issues/3755
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With