ken
ken

Reputation: 9013

Function signature for AWS Lambda Callback

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:

enter image description here

Upvotes: 2

Views: 634

Answers (1)

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

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

Related Questions