You are correct in that the issue is the same in the question you linked. Per said question's accepted answer:
But the ability to subtype doesn't just apply to adding additional properties -- subtyping can include choosing a more restricted set of the domain of the properties themselves.
For example, assume the following interface:
interface RestrictedValues extends UserValues {
avatar: "nonexistent"
}
This interface does extend UserValues
, and is thus assignable to MoreValues
. However, its avatar
property can only have the value nonexistent
, so the Partial<>
which is set()
's first argument should only allow the value nonexistent
, not any string as UserValues
would imply. Take, for example, the following code:
class User<MoreValues extends UserValues = UserValues> extends Table<MoreValues>{
constructor(values:MoreValues) {
super(values);
const thing1: RestrictedValues = { avatar: "nonexistent", id: "", username: "" };
const thing2: MoreValues = thing1;
}
}
In this, thing1
cannot be assigned to thing2
, since it is not guaranteed that MoreValues
will not instantiated with, say, { avatar: "" }
, where the only accepted value is an empty string, to which "nonexistent"
is not assignable. Therefore, TypeScript throws the error:
Type 'RestrictedValues' is not assignable to type 'MoreValues'.
'RestrictedValues' is assignable to the constraint of type 'MoreValues', but 'MoreValues' could be instantiated with a different subtype of constraint 'UserValues'.
A simpler example of this is provided in this answer, using only booleans, which I recommend reading if you want to better understand the logic behind this behaviour.
That error is warning you, that your Generic Type P
can't be
assigned to {}
, since the Generic Type P
can be a more defined, or
restricted, to a particular type that can conflict with the default
value.
That means that the value {}
can't satisfy all the possible Types
that can be used by the Generic Type P
.
Let's create another example with only booleans that should be easier
to understand:
interface OnlyBoolIdentityInterface<T> {
(arg: T): T;
}
function onlyBoolGeneric<T extends boolean>(arg: T = false): T {
return arg;
}
if you define a Type that is more specific than a boolean for example:
type TrueType = true;
and if you specialised the function OnlyBoolIdentityInterface
to
only support true values like this:
const onlyTrueIdentity: OnlyBoolIdentityInterface<TrueType> = onlyBoolGeneric;
even if TrueType respects the constraint set by T extends boolean
the default value arg: T = false
is not a TrueType
.
This is the situation is what the error is trying to convey to you.
So how can you fix this type of errors?
- Or you remove the default value
- Or T needs to extend the specialised type of the default param that on my example is false
- Or T can interfere directly with params that receive default params
For more context about this error message see the issue that suggested
this error message
https://github.com/Microsoft/TypeScript/issues/29049.