英文:
Typescript using object spread to satisfy a generic union type
问题
result: {
type: animalType,
fedBy: byWhom,
...params,
},
英文:
Given a union type with common fields type
and fedBy
. I want to write a function that takes in an Animal
as the type and a second argument with the params unique to that animal. I can get the signature and inference working, but doing something wrong in how to return the result.
type FeedAnimalParams =
| {
type: 'Dog'
fedBy: string
bowl: true
}
| {
type: 'Cat'
fedBy: string
fish: string
}
| {
type: 'Bird'
fedBy: string
seed: string
}
I'm inferring a literal type, pulling out the type
property
type Animal = FeedAnimalParams['type']
//type Animal = "Dog" | "Cat" | "Bird"
I'm pulling the unique fields required for each animal using a generic.
type UniqueAnimalParams<T extends Animal> = Omit<Extract<FeedAnimalParams, { type: T }>, 'type' | 'fedBy'>
type FeedResult<T> = {
message: string
result: T
}
Here's the function I'm trying to write
function feed<T extends Animal>(
byWhom: string,
animalType: T,
params: UniqueAnimalParams<T>,
): FeedResult<FeedAnimalParams> {
return {
message: `Fed by ${byWhom}`,
result: { //compile error here
type: animalType,
fedBy: byWhom,
...params,
},
}
}
//other lib
function CantChangeSignature(input:FeedAnimalParams){
console.log(input)
}
I get the intellisense when calling the function, so inference appears to be working but the function doesn't compile.
feed('Colin', 'Bird', {
seed: 'Sunflower',
})
feed('Joe', 'Dog', {
bowl: true,
})
Edit:1
Trying to avoid changing the return type signature since I need to pass it into another function I can't change.
FeedResult<FeedAnimalParams>
//also tried this as the return type
FeedResult<Extract<FeedAnimalParams, {type:T}>>
答案1
得分: 1
function feed
byWhom: string,
animalType: T,
params: UniqueAnimalParams
): FeedResult<UniqueAnimalParams
return {
message: Fed by ${byWhom}
,
result: {
type: animalType,
fedBy: byWhom,
...params,
},
}
}
英文:
You need to relate to the return type to the generic otherwise TS can't make the return value to be specific to the passed animalType
so it thinks it's all of them all at once.
function feed<T extends Animal>(
byWhom: string,
animalType: T,
params: UniqueAnimalParams<T>,
): FeedResult<UniqueAnimalParams<T> & {type: T, fedBy: string}> {
return {
message: `Fed by ${byWhom}`,
result: {
type: animalType,
fedBy: byWhom,
...params,
},
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论