This is because your intersection type conflicts with each other. You try to intersect an object which can be accessed with string
, and tell it returns string, and yet errorCounts
instead returns a number
. This type-safety is to prevent a user from doing something like this
const abc = doSomething<'errorsCount'>()
abc.errorsCount //=> never
The simple solution is to cast it.
const doSomething = <T extends string>(): ValidationErrors<T> => {
const errors = {
errorsCount: 0,
} as ValidationErrors<T>
return errors
}
The longer answer is because generics are used to augment function parameters, as such your doSomething
function has no parameters, and since all types are erased at compile time, it gives you this error since it will have no idea if it can guarantee the type of T
as being as intended. The preferred way for representing this behavior is to do something like this.
export type ValidationErrors2={
[index: string]: string | number
errorsCount: number;
}
const doSomething2 = (): ValidationErrors2 => {
const errors: ValidationErrors2 = {
errorsCount: 0,
}
return errors
}
Here is a similar example of what you tried to do originally, and this error message gets at the crux of what TypeScript is doing here.
export type ValidationErrors3<T extends Object> = T & {
errorsCount: number;
}
const doSomething3 = <T extends Record<Exclude<string, 'errorsCount'>, string>>(): ValidationErrors3<T> => {
//error VVV
const errors: ValidationErrors3<T> = {
errorsCount: 0,
}
return errors
}
Type '{ errorsCount: number; }' is not assignable to type 'T'. 'T' could be instantiated with an arbitrary type which could be unrelated to '{ errorsCount: number; }'.
However, this goes beyond the scope of your question probably. Read more specifically about Object types and subtypes and how this contributes to the issue you face How to fix TS2322: "could be instantiated with a different subtype of constraint 'object'"?
Another answer specifically related to your question, in this case it describes the multiple ways to go about typing a intersection like yours.