I am using the Directus API with Typescript. With Typescript, its API calling functions return partial entities (eg. PartialItem<Book>), so I'm diligently checking the existence of required properties before passing the data onward.
However, I'm still getting Typescript type errors which are unrelated to Directus specifically but perhaps with how I'm handling the partial type.
Here's a simplified example with pure Typescript (and on TS Playground):
interface Book {
id: string;
title?: string;
author?: string;
pages?: number;
}
class Library {
static books: Book[] = [];
static addBook(data: Partial<Book> & {id: string}) {
this.books.push(data);
}
}
function fetchBooks(): Promise<Partial<Book>[]> {
return new Promise((resolve)=>{
setTimeout(()=>{
resolve([
{id: "1234",title:"Nineteen Eighty-Four"},
{id: "2345", title: "The Great Gatsby", author: "F. Scott Fitzgerald"}
])
},1000)
})
}
function bookLoadingFunction() {
fetchBooks().then(books=>{
books.map(b=>{
if(!b.id){
// Handle the fact that the API is missing ID
}else{
Library.addBook(b); // * COMPILE ERROR HERE *
}
})
})
}
Even after checking, the compiler doesn't appear to be able to infer that b.id is defined. And I get the following error:
Argument of type 'Partial<Book>' is not assignable to parameter of type 'Partial<Book> & { id: string; }'.
Type 'Partial<Book>' is not assignable to type '{ id: string; }'.
Types of property 'id' are incompatible.
Type 'string | undefined' is not assignable to type 'string'.
Type 'undefined' is not assignable to type 'string'.
Is this a limitation of the compiler, or does there exist an edge case where b.id could indeed still be undefined? And is there a way to keep the compiler happy without losing type safety?
I know the following would make the errors go away, but it's far from ideal:
Library.addBook(b as Partial<Book> & {id: string});
Thanks.