如何将子接口传递给父类?



我有这个:

LocationController.ts

import {GenericController} from './_genericController';
interface Response {
id : number,
code: string,
name: string,
type: string,
long: number,
lat: number
}
const fields = ['code','name','type','long','lat'];
class LocationController extends GenericController{
tableName:string = 'location';
fields:Array<any> = fields;
}
const locationController = new LocationController();
const get = async (req, res) => {
await locationController._get(req, res);
}
export {get};

GenericController.ts


interface Response {
id : number
}
export class GenericController{

tableName:string = '';
fields:Array<any> = [];
_get = async (req, res) => {
try{
const id = req.body['id'];
const send = async () => {
const resp : Array<Response> = await db(this.tableName).select(this.fields).where('id', id)
if (resp[0] === undefined) {
// some error handling
}
res.status(status.success).json(resp[0]);
}
await send();
}catch (error){
// some error handling
}
}    
}

我想做的是将Response接口从LocationController传递给GenericController父接口,以便根据子类定义它的方式准确地键入响应。显然,它不是这样工作的,因为接口是在类之外定义的,所以父类不知道LocationController中的Response接口。ts文件

我已经试过在构造函数中传递接口作为参数,这不起作用。有什么办法能让我做到吗?我觉得我错过了一些非常简单的东西。

通常在这种情况下使用泛型。我是这样做的:

interface Response {
id: number;
}
// Note the generic parameter <R extends Response>
export class GenericController<R extends Response> {
tableName: string = "";
fields: Array<any> = [];
_get = async (req, res) => {
try {
const id = req.body["id"];
const send = async () => {
// The array is now properly typed. You don't know the exact type,
// but you do know the constraint - R is some type of `Response`
let resp: Array<R> = await db(this.tableName).select(this.fields).where("id", id);
if (resp[0] === undefined) {
// some error handling
}
res.status(status.success).json(resp[0]);
};
await send();
} catch (error) {
// some error handling
}
};
}
import { GenericController } from "./_genericController";
interface Response {
id: number;
code: string;
name: string;
type: string;
long: number;
lat: number;
}
const fields = ["code", "name", "type", "long", "lat"];
// Here we tell the GenericController exactly what type of Response it's going to get
class LocationController extends GenericController<Response> {
tableName: string = "location";
fields: Array<any> = fields;
}
const locationController = new LocationController();
const get = async (req, res) => {
await locationController._get(req, res);
};
export { get };

如果这还不够,并且您希望以某种方式知道您将获得的确切响应类型,我相信唯一的方法是手动检查。例如:

import { LocationResponse } from './locationController';
// ... stuff
// Manual runtime type check
if (this.tableName === 'location') {
// Manual cast
resp = resp as Array<LocationResponse>
}
// ...

您还可以检查resp[0](if (resp[0].hasOwnProperty('code')) { ... })的形式并相应地强制转换。也有更好的写法,但基本思想是一样的。

一般来说,一个正确编写的类应该不知道从它继承的任何类。将特定于子类的逻辑放入通用控制器是一种代码气味。尽管和往常一样,这一切都取决于特定的情况。

最新更新