// ============ An example using dependent types to overload function signatures ============ // In this example, we define a type CertCheckResponse which defines the structure of a response // object for a hypothetical certificate validation API. // We then implement a function sendCheckResponse whose return type and parameter signature // depends on the value of the success parameter. /** A helper function that gets a Date one hour in the future. */ function inOneHour(): Date { const d = new Date() d.setMinutes(d.getMinutes() + 60) return d } /** A type conditional on a boolean parameter. */ type CertCheckResponse = Success extends true ? {issuer: string, expires: Date} : {error: string} // Hover over the identifier to view the computed types. type ExampleSuccess = CertCheckResponse type ExampleFail = CertCheckResponse /** * This is where the magic happens. We combine TypeScripts function/method overloading with * the dependent types to make not only the return type but also the function signature dependent * on the value of the `success` parameter. * * (The third and final signature is the signature of the underlying implementation and must be * compatible with all the other signatures.) * * @param success * @param issuer * @param expires */ function sendCheckResponse(success: true, issuer: string, expires: Date): CertCheckResponse function sendCheckResponse(success: false, error: string): CertCheckResponse function sendCheckResponse(success: boolean, issuerOrError: string, expires?: Date): CertCheckResponse function sendCheckResponse(success: boolean, issuerOrError: string, expires: Date = new Date()): CertCheckResponse { if ( success ) { return { issuer: issuerOrError, expires: expires, } } return {error: issuerOrError} } const successResponse = sendCheckResponse(true, 'contoso.com', inOneHour()) // => {issuer: string, expires: Date} const failureResponse = sendCheckResponse(false, 'Invalid issuer.') // => {error: string} // Interestingly, this gracefully degrades to more general types when the value // of success cannot be inferred statically. This is why we include the 3rd overload // signature with `success: boolean`. let someBool!: boolean // example of a non-specific boolean value // This has the union type {issuer: string, expires: Date} | {error: string} const ambiguousResponse = sendCheckResponse(someBool, 'String?')