Reputation: 9013
I wanted to create a Typescript for AWS Lambda's callback function and must be doing something dumb because I'm getting errors on something that seems easy. The way I'm approaching it is to have two function definitions for a SUCCESS and FAILURE condition and then to wrap them together as a discriminated union.
So here are my types:
export interface ILambdaSuccessCallback<T = IDictionary> {
(error: null, response: T): void;
}
export interface ILambdaFailureCallback<E = ILambdaErrorResponse> {
(error: string | number, response: E): void;
}
export interface ILambdaErrorResponse<T = any> {
errorCode?: string | number;
message?: string;
errors?: T[];
stackTrace?: string[];
}
/** Discriminated Union */
export type LambdaCallback<T = IDictionary, E = ILambdaErrorResponse> =
| LambdaSuccessCallback<T>
| LambdaFailureCallback<E>;
I've now included my little visual test in vs-code showing the behavior or explicit use of failure and success but also, more importantly, the discriminated union which is just not working:
Upvotes: 2
Views: 634
Reputation: 249686
Union types (defined with |
) represent a type that can be either ILambdaSuccessCallback
or ILambdaFailureCallback
which means that neither signature is callable because the compiler can't check which is valid. With union types you only have access to common fields and signatures and ILambdaSuccessCallback
and ILambdaFailureCallback
have no properties or signatures in common,
If your function can handle both signatures you want an intersection type (defined with &
)
export type LambdaCallback<T = IDictionary, E = ILambdaErrorResponse> =
& ILambdaSuccessCallback<T>
& ILambdaFailureCallback<E>;
const either: LambdaCallback = function (err: null | string | number, con: IDictionary | ILambdaErrorResponse) {
}
either(null, {}) // Works
either(500, {}) // Works
The second failure
call (failure(null, {})
) works, because in Typescript, null
and undefined
are subtypes of all types (see the spec) and thus you can assign null
to string | number
you can enable strictNullChecks
to make the compiler forbid this scenario (but this might cause a lot of other warnings)
Upvotes: 1