As a follow-up to my previous question...
Is there a way to provide a default value for valueProp
in the following example?
type ValueType = 'value' | 'defaultValue'
type Props<T extends ValueType> =
Record<T, string>
& { other: string }
function props<T extends ValueType>(valueProp: T): Props<T> {
return {
[valueProp]: 'value',
other: 'other',
} as Props<T>
}
let { defaultValue, other } = props('defaultValue') // ok
let { value } = props('value') // ok
When I try this:
function props<T extends ValueType>(valueProp: T = 'value'): Props<T> {
return {
[valueProp]: 'value',
other: 'other',
} as Props<T>
}
, I get this error:
Type '"value"' is not assignable to type 'T'.
'"value"' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'ValueType'.
I understand this error (1, 2, 3, 4) in general, but still don't always know the best way to resolve this error.
Is there an easy way to do what I'm trying to do?
It just seems like there ought be an easy way to provide a default value, but maybe default values just don't mix so well with generic type constraints?
Default type for the generic type?
I tried this:
function props<T extends ValueType = 'value'>(valueProp: T = 'value'): Props<T> {
return {
[valueProp]: 'value',
other: 'other',
} as Props<T>
}
but of course got the same error, because T could still be defaultValue
if a specific T
is provided:
props<'defaultValue'>()
Type assertions?
I thought of doing this, which compiles, but still doesn't prevent valueProp
from disagreeing with T:
function props<T extends ValueType>(valueProp: T = 'value' as T): Props<T> {
return {
[valueProp]: 'value',
other: 'other',
} as Props<T>
}
console.log(props<'defaultValue'>())
// => {value: "value", other: "other"}
Something more complicated?
I'm still hoping there's a simple solution, but if not, maybe something more complicated would work?
Maybe using a mapping table that maps from a type to the default value for that type?
For inspiration, maybe something kind of like: