Reputation: 20276
According to this example from the TypeScript documentation, if I want to define a type for objects with multiple properties that all have the same type, I can use the Record
utility type, like this:
interface CatInfo {
age: number;
breed: string;
}
type CatName = 'miffy' | 'boris' | 'mordred';
type Cats = Record<CatName, CatInfo>;
function logCat(cats: Cats, catName: CatName) {
console.log(cats[catName]);
}
const myCats = {
miffy: { age: 10, breed: 'Persian' },
boris: { age: 5, breed: 'Maine Coon' },
mordred: { age: 16, breed: 'British Shorthair' }
};
logCat(myCats, 'boris');
This works well, as long as my object myCats
has properties for each of the cat names defined in the type CatName
.
However, when I send an object to logCat
that does not contain cat info for all of the cat names, like this:
logCat(
{
boris: { age: 5, breed: 'Maine Coon' },
mordred: { age: 16, breed: 'British Shorthair' }
},
'boris'
);
…I get an error from the TypeScript compiler, complaining that my cats object does not contain any info for cat “miffy”:
I've tried to do something clever like this to fix it, but that didn't work:
type Cats = Record<Partial<CatName>, CatInfo>;
How can I define a type that allows me to control which property names for an object are valid, whilst not all property names need to be used in the object?
Upvotes: 2
Views: 144
Reputation: 8403
You can set the type of the parameter cats
to Partial<Cats>
.
function logCat(cats: Partial<Cats>, catName: CatName) {
console.log(cats[catName]);
}
Works:
logCat(myCats, 'boris');
logCat(
{
boris: { age: 5, breed: 'Maine Coon' },
mordred: { age: 16, breed: 'British Shorthair' }
},
'boris'
);
Fails:
logCat(
{
boris: { age: 5, breed: 'Maine Coon' },
mordred: { age: 16, breed: 'British Shorthair' },
dog: { foo: 16, breed: 'Not cat' }
},
'boris'
);
logCat(
{
boris: { age: 5, breed: 'Maine Coon' },
mordred: { age: 16, breed: 'British Shorthair' },
dog: { age: 16, breed: 'Not cat' }
},
'boris'
);
logCat(
{
boris: { age: 5, breed: 'Maine Coon' },
mordred: { age: 16, breed: 'British Shorthair' },
'dog'
},
'boris'
);
Upvotes: 2