How can I make a generic template type argument required?
So far, the only way I found to do it is using never
but it causes an error to happen at a different place other than the callsite of the generic.
The TypeScript Playground example pasted here:
type RequestType =
| 'foo'
| 'bar'
| 'baz'
interface SomeRequest {
id: string
type: RequestType
sessionId: string
bucket: string
params: Array<any>
}
type ResponseResult = string | number | boolean
async function sendWorkRequest<T extends ResponseResult = never>(
type: RequestType,
...params
): Promise<T> {
await this.readyDeferred.promise
const request: SomeRequest = {
id: 'abc',
bucket: 'bucket',
type,
sessionId: 'some session id',
params: [1,'two',3],
}
const p = new Promise<T>(() => {})
this.requests[request.id] = p
this.worker.postMessage(request)
return p
}
// DOESN'T WORK
async function test1() {
const result = await sendWorkRequest('foo')
result.split('')
}
test1()
// WORKS
async function test2() {
const result = await sendWorkRequest<string>('foo')
result.split('')
}
test2()
As you see in the call to test1()
, the error happens at result.split('')
because never
does not have a .split()
method.
In test2
it works great when I provide the generic arg.
How can I make the arg required, and not use never, and for the error to happen on the call to sendWorkRequest
if a generic arg is not given?
function foo<T=never>(bar: T)
doesn't work because, when T is not specified, TypeScript will infer T from the type of bar. Whilefunction foo<T=never, U extends T=T>(bar: U)
works because T cannot be automatically inferred and will default to never, and fail as we intended. – Mcgann