Im building an app using angular 5 ( TS ),
i got stuck trying to initiate an empty object of my interface.
So the only acceptable solution i have seen is this one:
article: Article = {} as Article;
Although its seems legit it doesn't work;
trying to use article["something"] will fail because its just an empty object without any keys .
The result im seeking looks something like this:
export interface Article {
slug: string;
title: string;
description: string;
body: string;
tagList: string[];
after init:
article = { 'slug': '', 'title': '', 'description': '', body: '', tagList: '[]' }
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' });
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
Interfaces (and types in general) are just a compile time construct to help the compiler validate our code, as such the type assertion you use ({} as Article
) will do nothing more than to tell the compiler that empty object literal has that shape. If you want to have an 'empty' object for your interface, you will have to create it yourself:
interface Article {
slug: string;
title: string;
description: string;
body: string;
tagList: string[];
}
function emptyArticle(): Article {
return {
slug: '',
title: '',
description: '',
body: '',
tagList: []
}
}
The good news is that the compiler will warn you if you forget to add a default for any of the mandatory field.
Or if you want to make sure optional field are also specified you can create a mapped type that removes the optional from the fields.
type Mandatory<T> = { [P in keyof T]-?: T[P] };
function emptyArticle(): Mandatory<Article> {
return {
....
}
}
Here is another way to initialize. Worked for me:
const article: Article = ({} as any) as Article;
When you want to initialize an object without properties, then have to declare it that it is valid without properties. Also the properties have to be optional:
export interface Article {
slug?: string;
title?: string;
description?: string;
body?: string;
tagList?: string[];
}
when not you have to initialize the object as you mentioned already
article = { 'slug': '', 'title': '', 'description': '', body: '', tagList: '[]' }
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