Is there a way to type a property of an object as you’re writing the object? As opposed to defining a type/interface beforehand.
The only thing I can think of is as
but that’s too lenient. Consider:
type Comment = Required<{
author: string;
message: string;
}>;
const myComment: Comment = {
author: 'Steve',
// Error! :) 'message' is missing
};
const myData = {
myComment: {
author: 'Steve',
// No error. :(
} as Comment,
};
const myData = {
myComment: <Comment>{
author: 'Steve',
// No error. :(
},
};
I want myData.myComment
to throw the same error.
This is a trivial example, of course. But if I'm writing a big complex object it would be nice to be able to declare types for portions of it on-the-fly.
CodePudding user response:
Would an anonymous/inline interface work? You still need it to precede the object but it's more concise than interface
/type
:
const myData: { myComment: Comment } = {
myComment: {
author: 'Steve',
// error
},
};
CodePudding user response:
One option is to use IIFEs, although it's ugly and has (extremely) minor performance implications:
const myData = {
myComment: ((): Comment => ({
author: 'Steve',
// Error! 'message' is missing
}))(),
};
CodePudding user response:
Perhaps this is what you're asking: https://stackoverflow.com/a/12787919/4771663
You can declare the object literal type during the assignment:
const myData: { myComment: Comment } = {
myComment: {
author: 'Steve',
}
}
CodePudding user response:
Note:
Comment
is a built-in type inlib.dom.d.ts
. If you use that identifier with thedom
library, you'll get this error:Duplicate identifier 'Comment'.(2300)
You can use an identity function to ensure that the input is assignable to the parameter type:
type C = {
author: string;
message: string;
};
/** If you use this, you MUST provide the generic type argument to constrian your value */
function id <T>(value: T): T {
return value;
}
const number1 = id<number>('hello'); /*
^^^^^^^
Argument of type 'string' is not assignable to parameter of type 'number'.(2345)
*/
// Don't forget to supply the generic type argument!
const number2 = id('hello'); // typeof value2 === "hello"
const myData1 = {
myComment: id<C>({
author: 'Steve',
// message: 'Hi',
}), /*
^^^^^^^^^^^^^^^^^^^^^^^^^
Argument of type '{ author: string; }' is not assignable to parameter of type 'C'.
Property 'message' is missing in type '{ author: string; }' but required in type 'C'.(2345) */
};
const myData2 = {
myComment: id<C>({
author: 'Alex',
message: 'Hello',
}), // ok
};
console.log(myData1); // { myComment: { author: 'Steve' } }
console.log(myData2); // { myComment: { author: 'Alex', message: 'Hello' } }
Alternatively, if you're simply trying to avoid typing, you can define the comment ahead of the object in which you want to include it, like this:
type C = {
author: string;
message: string;
};
let myComment: C = {
author: 'Steve',
message: 'Hi',
};
const myData1 = { myComment };
myComment = {
author: 'Alex',
message: 'Hello',
};
const myData2 = { myComment };
console.log(myData1); // { myComment: { author: 'Steve', message: 'Hi' } }
console.log(myData2); // { myComment: { author: 'Alex', message: 'Hello' } }
console.log(myComment); // { author: 'Alex', message: 'Hello' }