Reputation: 21
I want to have an interface where the generic type is based on the value of a property in this interface:
interface Book<T extends BookType> {
type: T,
location: Shelf<T>,
}
Instead of using the following to define the generic type:
const book: Book<BookType.Technology>;
I want
const book: Book<???>;
book.type = BookType.Technology;
And afterwards, location
is "hinted" to have type Shelf<BookType.Technology>
Is this possible in TypeScript?
Upvotes: 2
Views: 1796
Reputation: 328262
TypeScript doesn't really support making empty objects and then assigning properties later the way you want to do it. Usually the workaround here is to use a type assertion to strongly type the empty object... but you don't want to write out the full type Book<BookType.Technology>
yourself, so that's not a good suggestion. You'd like type inference for the BookType.Technology
part, but that won't work because the compiler has no idea that type
will be BookType.Technology
until the next line. And type narrowing doesn't work backwards.
Best practice in TypeScript is to make a strongly-typed object in a single statement instead of adding individual properties in multiple statements. This is a lot easier for the compiler to understand. If that's okay, then I'd suggest using a helper function which will infer the T
in Book<T>
for you. Like this:
const asBook = <T extends BookType>(book: Book<T>) => book;
When you use it:
asBook({
type: BookType.Technology,
location: ... // this is hinted as Shelf<BookType.Technology>
})
the type of location
will be hinted for you as Shelf<BookType.Technology>
as you wanted.
Hope that helps; good luck!
Upvotes: 1