It's not possible to create a type which forces to be { a } or { a, b, c }. This is called Discriminated Unions and you can read more about this problem here.
You can use booth approaches which @SimonRosengren mentioned. To force typesafety when defining an object you have to implicitly say which type is what:
interface FilterTypeBase {
name: { value: string, rank: string },
place: { value: string, population: string }
}
interface FilterTypeExtended extends FilterTypeBase {
description: { value: string, translation: string },
popularity: { value: string, ranking: string }
}
// 👍 OK
const filters: FilterTypeBase = {
name: { value: 'some-value', rank: 'some-value' },
place: { value: 'some-value', population: 'some-value' },
}
// ❌ ERROR: Property 'popularity' is missing
const filters2: FilterTypeExtended = {
name: { value: 'some-value', rank: 'some-value' },
place: { value: 'some-value', population: 'some-value' },
description: { value: "string", translation: "string" }
}
If you use want to decide in a function which of booth variantes your type is. You can do this with narrowing:
type FilterType = FilterTypeBase | FilterTypeExtended
function doSomething(filter: FilterType) {
if('description' in filter) {
// Here it's the extended type
}
}
Typescript docs: Narrowing