I have this example which works well:
export type TimeStamped<TContent, TContentName extends string> = {
[P in TContentName]: TContent
}
type Food = 'apple' | 'banana' | 'pear'
type TimeStampedFood = TimeStamped<Food, 'food'>
type Animal = 'cat' | 'dog' | 'horse'
type TimeStampedAnimal = TimeStamped<Animal, 'animal'>
const banana: TimeStampedFood = {food: 'banana'}
const cat: TimeStampedAnimal = {animal: 'cat'}
console.log(banana, cat)
It's a bit pointless though. So let's keep track of the creation and expiry dates of these objects, like so:
export type TimeStamped<TContent, TContentName extends string> = {
[P in TContentName]: TContent,
createdAt: DateTimeString,
expiresAt?: DateTimeString
}
type Food = 'apple' | 'banana' | 'pear'
type TimeStampedFood = TimeStamped<Food, 'food'>
type Animal = 'cat' | 'dog' | 'horse'
type TimeStampedAnimal = TimeStamped<Animal, 'animal'>
const banana: TimeStampedFood = {
food: 'banana',
createdAt: '2020-01-01T00:00:00Z',
expiresAt: '2020-01-01T01:00:00Z'
}
const cat: TimeStampedAnimal = {
animal: 'cat',
createdAt: '2016-01-01T00:00:00Z',
expiresAt: '2023-01-01T01:00:00Z'
}
console.log(`The ${banana.food} expires at ${banana.expiresAt}`)
This wont work so well because I get an error on the type declaration:
Expecting newline or semicolon
Unnecessary label 'createdAt'
TS2304: Cannot find name 'expiresAt'
TS1128: Declaration or statement expected.
My goal is to have an object with createdAt
and optionally expiresAt
properties defined but the property for the content should allow any name. Is there a way of doing what I'm trying to do?.
CodePudding user response:
You can't do it that way, see e.g. How to combine known interface properties with a custom index signature?
Docs: https://www.typescriptlang.org/docs/handbook/2/objects.html#index-signatures
How about one of these options:
export interface TimeStamped {
createdAt: DateTimeString;
expiresAt: DateTimeString;
}
type Food = 'apple' | 'banana' | 'pear'
type TimeStampedFood = { food: Food; } & TimeStamped;
// https://www.typescriptlang.org/docs/handbook/2/objects.html#intersection-types
type Animal = 'cat' | 'dog' | 'horse'
interface TimeStampedAnimal extends TimeStamped {
animal: Animal;
}
// https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#interfaces
const banana: TimeStampedFood = {
food: 'banana',
createdAt: '2020-01-01T00:00:00Z',
expiresAt: '2020-01-01T01:00:00Z'
}
const cat: TimeStampedAnimal = {
animal: 'cat',
createdAt: '2016-01-01T00:00:00Z',
expiresAt: '2023-01-01T01:00:00Z'
}