An interface does not define an initial value for actual objects, but defines the requirements an object must meet for it to be an implementation of that interface.
You should create a factory of some kind that creates objects of type Article, this could be as simple as this function:
const emptyArticle = (): Article => ({
slug: '',
title: '',
description: '',
body: '',
tagList: [],
});
You could additionally create a function that accepts an object that is a Partial<Article> - as described here. This enables you to pass a subset of initial values to the function. This example uses emptyArticle defined above:
const createArticle = <T extends Partial<Article>>(initialValues: T): Article & T => {
return Object.assign(emptyArticle(), initialValues);
};
// Initialize a new article with a certain slug:
createArticle({ slug: 'my-awesome-article' });
Answer from JJWesterkamp on Stack OverflowAn interface does not define an initial value for actual objects, but defines the requirements an object must meet for it to be an implementation of that interface.
You should create a factory of some kind that creates objects of type Article, this could be as simple as this function:
const emptyArticle = (): Article => ({
slug: '',
title: '',
description: '',
body: '',
tagList: [],
});
You could additionally create a function that accepts an object that is a Partial<Article> - as described here. This enables you to pass a subset of initial values to the function. This example uses emptyArticle defined above:
const createArticle = <T extends Partial<Article>>(initialValues: T): Article & T => {
return Object.assign(emptyArticle(), initialValues);
};
// Initialize a new article with a certain slug:
createArticle({ slug: 'my-awesome-article' });
Or more simply replace Interface to Class by setting default values like:
export class Article {
slug: string = '';
title: string = '';
description: string = '';
body: string = '';
tagList: string[] = [];
}
When let article = new Article() it will already have properties with default values
Add exactly empty object ({} literal) type
Empty interface allow any object?
How should a variable initialized to empty object be assigned an interface before it is returned?
typescript - Empty interface allow any object? - Stack Overflow
I know this is a really basic question, and I've tried to look at similar questions and didn't understand it so I apologize.
I'm translating my JavaScript code to TypeScript, and have a lot of code that looks similar to this:
if (!user_dict.options) {
user_dict.options = {}
}This produces the error "property options does not exist on type {}" for both lines. How can I establish an empty object like this, if I don't know what type of variables will later be stored? I have hundreds of empty variable declarations like this, and I can't know at this point in the code the "type" of variable being stored later, so I don't understand how I'm supposed to handle this using TypeScript?
I have hundreds of empty variable declarations like this, and I can't know at this point in the code the "type" of variable being stored later,
You don't know what sort of data you're planning on putting in the variable?
"property options does not exist on type {}"
Do it basically tells you that user_dict type doesn’t contain ‘options’ property. You need to add it to user_dict type or interface. Or if you don’t have type for this object you’d better write it.
export default interface ConfigData {
languageCode : string
, numberOfRepeats : number
}Probably a basic thing for you guys to sort out. I'm thinking on initialization, allow TS to infer variable type, then enforce the interface as return type:
run() {
// data to be returned at end
const configData = {};
this.steps.forEach(async (configStep: WizardSteps): ConfigData => {
// capture answer
const rawUserResponse: string|void = await configStep.explain();
if (configStep.needsValidation) {
// loops until validated
const validatedInput: string = configStep.validatedInput(rawUserResponse);
if (configStep.hasSaveableData) {
// convert to k/v pair
const formattedForConfiguration = configStep.format(rawUserResponse);
// save to local object
Object.assign(configData, formattedForConfiguration);
}
}
})
return configData;
}Is this the proper pattern? If not, how should an interface enforce types on something that is initially set to one value and then mutated?
This behavior is intentional.
The excess property check is not performed when the target is an empty object type since it is rarely the intent to only allow empty objects.
Actually, you can assign {a: 1} to B, the other answers here are mostly wrong.
You have stumbled upon another slightly confusing quirk in TypeScript, namely that you can not directly assign an object literal to a type where the object literal contains other properties than the one specified in the type.
However, you can assign any existing instance of an object to a type, as long as it fulfill the type.
For example:
interface Animal {
LegCount: number;
}
let dog: Animal = { LegCount: 4, Fur: "Brown" }; // Nope
var myCat = { LegCount: 4, Fur: "Black" };
let theCat: Animal = myCat; // OK
This constraint is simply ignored whey you have a type that is empty.
Read more here and here.
A later answer from the Typescript team is available on GitHub.
Okay, interesting question.
Test Case 1:
interface A {};
interface B extends A {
b?: any;
}
const a: A = {a: 1};
console.log(a);
It passes, as A is an empty interface, whatever you dumb inside is going to return back. Works like a class Object
Test Case 2:
interface A {};
interface B extends A {
b?: any;
}
const a: A = {b: 1};
console.log(a);
Just changed the value a to b just to prove first test case. It passes.
Test Case 3:
interface A {};
interface B extends A {
b?: any;
}
const a: B = {a: 1};
console.log(a);
It fails, because there is no prop inside interface A or B that is named a
Test Case 4:
interface A {};
interface B extends A {
b?: any;
}
const a: B = {b: 1};
console.log(a);
It passes, as interface B has a prop named b
I hope this helps you understand.
PS: prop refers to property.
Take this as an analogy: Interface A is a empty house, dumb whatever you want. It wont utter a word. Interface B is a house in a colony, which means it needs behave specifically to size, shape and needs to stick to Interface A. Which means Interface B is not more a empty and is restricted with rules.