Home > Back-end >  Typescript correct function typing
Typescript correct function typing

Time:01-27

I'm new to typescript and I'm not quite sure how to properly describe the return value type of a function. I have some abstract class and method

import { Request, Response, NextFunction } from 'express';

export interface RequestMiddleware {
    (req: Request, res: Response, next: NextFunction): void
}

export abstract class ValidateRequest {
    abstract checkData(params?: any[]): RequestMiddleware
}

And the class that inherits this abstract and implements the method

import { Request, Response, NextFunction } from 'express';
import { ValidateRequest, RequestMiddleware } from './contract/ValidateRequest';


class AuthSignUp extends ValidateRequest {
    checkData(params?: any[]): RequestMiddleware {
        return (req: Request, res: Response, next: NextFunction) => {

        }
    }
}

export default new AuthSignUp();

But I noticed that I can remove the arguments (or change the number of arguments) and typescript will not give errors

import { Request, Response, NextFunction } from 'express';
import { ValidateRequest, RequestMiddleware } from './contract/ValidateRequest';


class AuthSignUp extends ValidateRequest {
    checkData(params?: any[]): RequestMiddleware {
        return () => {}
    }
}

export default new AuthSignUp();

How to do the correct typing, i.e., that the arguments of the return function checkData correspond to the described interface RequestMiddleware?

CodePudding user response:

TypeScript allows for function implementations with lower arity by design. For example:

TS Playground

type AddTwo = (a: number, b: number) => number;

const first: AddTwo = (a, b) => a   b; // ok
const second: AddTwo = (a) => a; // ok
const third: AddTwo = () => 0; // ok

This is described in the Overloads and Callbacks section of the handbook:

Overloads and Callbacks

Don't write separate overloads that differ only on callback arity:

/* WRONG */
declare function beforeAll(action: () => void, timeout?: number): void;
declare function beforeAll(
  action: (done: DoneFn) => void,
  timeout?: number
): void;

Do write a single overload using the maximum arity:

/* OK */
declare function beforeAll(
  action: (done: DoneFn) => void,
  timeout?: number
): void;

Why: It's always legal for a callback to disregard a parameter, so there's no need for the shorter overload. Providing a shorter callback first allows incorrectly-typed functions to be passed in because they match the first overload.

  • Related