Reputation: 186
Say we have a type defined like so:
type PropsBase<T> = {
optionalProp?: T;
}
type Props<T, TAdditionalProps extends object> = PropsBase<T> & TAdditionalProps
Basically I have a common properties object and then child classes can add some more properties if they need them. Then I want to use it like that:
type State<T> = {
value: T;
}
abstract class Base<T, TAdditional extends object = {}> {
state: State<T>;
constructor(props: Readonly<Props<T, TAdditional>>) {
this.state = {
value: props.optionalProp || this.fallbackValue() // ERROR!
}
}
abstract fallbackValue(): T;
}
This causes the following error:
TS2322: Type 'T | Props<T, TAdditional>["optionalProp"]' is not assignable to type 'T'.
'T' could be instantiated with an arbitrary type which could be unrelated to
'T | Props<T, TAdditional>["optionalProp"]'.
If I make optionalProp
not optional (remove ?
) then it works, it also works if I remove Readonly
from constructor and just use Props<T, TAdditional>
instead.
So my question is: why is this happening? and is there a way to still use Readonly
here and have an optional property?
P.S. I have strict: true
in my tsconfig.json. I know that if I set it to false
it'll work.
Upvotes: 2
Views: 74
Reputation: 58
I think switching from || to ?? fixes your problem.
type PropsBase<T> = {
optionalProp?: T;
}
type Props<T, TAdditionalProps extends object> = PropsBase<T> & TAdditionalProps
type State<T> = {
value: T;
}
abstract class Base<T, TAdditional extends object = {}> {
state: State<T>;
constructor(props: Readonly<Props<T, TAdditional>>) {
this.state = {
value: props.optionalProp ?? this.fallbackValue()
}
}
abstract fallbackValue(): T;
}
Upvotes: 2
Reputation: 701
Yes, strict mode doesn't work very well. But my reason to use it was strictBindCallApply
and strictNullChecks
. So my answer is – set property by property:
{
"compilerOptions": {
"strictBindCallApply": true,
"strictNullChecks": true
}
}
Upvotes: 0