基于泛型类类型的类方法参数类型

时间:2018-04-26 14:10:58

标签: typescript

class Route<T> {
  path: string;

  constructor(path: string) {
    this.path = path;
  }

  getLink(params: T) {
    if (!params) {
      return this.path;
    }

    return `${this.path}/${params.join('/')}`;
  }
}


const routeA = new Route<{ id: number }>('/something/amazing');

// should not be possible
routeA.getLink();

// only this should be valid
routeA.getLink({ id: 1 });

嗨 - 我想要一个带有通用参数T(params)的类Route。每条路线可能都有一些参数或根本没有。

然后应该可以调用routeA.getLink()并正确输入其参数。

const a = new Route('index'); // takes no parameters
a.getLink() // only this is valid
a.getLink({ something: 1}) // invalid

const b = new Route<{ id: number }>('post'); // takes no parameters
b.getLink() // invalid
b.getLink({ id: 1}) // valid

如何输入?

一些帮助真的很感激:) 谢谢!

1 个答案:

答案 0 :(得分:2)

您可以对null使用函数重载和默认值T,以确保某个重载仅对某个this有效:

class Route<T = null> {
    path: string;

    constructor(path: string) {
        this.path = path;
    }

    getLink(this: Route<null>): string;
    getLink(this: Route<T>, params: T): string;
    getLink(params?: T) {
        if (!params) {
            return this.path;
        }

        return `${this.path}/${params.join('/')}`;
    }
}


const a = new Route('index'); // takes no parameters
a.getLink() // only this is valid
a.getLink({ something: 1 }) // invalid


const b = new Route<{ id: number }>('post'); // takes no parameters
b.getLink() // invalid
b.getLink({ id: 1 }) // valid

另一种解决方案是将两个构造函数签名声明为泛型签名和非泛型签名,每个签名都返回不同的类型签名:

class RouteImpl<T> {
    path: string;

    constructor(path: string) {
        this.path = path;
    }

    getLink(params?: T) {
        if (!params) {
            return this.path;
        }

        return `${this.path}/${params.join('/')}`;
    }
}

const Route: {
    new (path: string) : { 
        path: string,
        getLink(): string;
    }
    new <T>(path: string) : { 
        path: string,
        getLink(params:T): string;
    }
} = RouteImpl;

const a = new Route('index'); // takes no parameters
a.getLink() // only this is valid
a.getLink({ something: 1 }) // invalid



const b = new Route<{ id: number }>('post'); // takes no parameters
b.getLink() // invalid
b.getLink({ id: 1 }) // valid