How do you avoid repeating types constantly when using generics in Typescript? If I have some constraint on a generic type then I must repeat that constraint anywhere I use the generic type. This is tedious and not very DRY.
//A constraint on this generic
type MyConstraint = { bar: number }
type GenericOne<T extends MyConstraint> = {
foo: T
}
To create an instance I annoyingly have to repeat the constraint because TS only does generic inference on functions
//This annoyance would I think be solved by generic values https://github.com/microsoft/TypeScript/issues/17574
const testok: GenericOne<MyConstraint> = { foo: { bar: 1 } }
Now if I want to use my generic type in other places I also have to repeat the constraint!
const makeGenericOne2: <T extends MyConstraint>(arg: GenericOne<T>) => GenericOne<T> = (arg) => {
return arg
}
At least now I can create from object literals without repeating myself
const test5 = makeGenericOne2({ foo: { bar: 1 } })
// And I get nice error messsages
const test6 = makeGenericOne2({foo: {baz: 1}})
The only way to avoid repeating the constraint seems to be a conditional type with inference
const makeGenericOne: <T>(arg: T extends GenericOne<infer U> ? T : never) => T = (arg) => {
return arg
}
I can still create instances from object literal without repeating myself
const test3 = makeGenericOne({ foo: { bar: 1 } })
But now the error messages aren't so nice.
//"number not assignable to never" instead of { baz: 1 } is missing property "bar: number"
const test4 = makeGenericOne({ foo: { baz: 1 } })
It seems like the following is needed -- infer T because we know it must extend Myconstraint
const propagateGeneric: <infer T>(arg: GenericOne<T>) => GenericOne<T>
Unfortunately this isn't allowed in TS at the moment.
How do I "propogate" the constraint on a generic type to avoid repeating it everywhere that generic type is used?