繁体   English   中英

typescript 扩展类型与接口

[英]typescript extending types vs interfaces

这可能是一个比较菜鸟的问题,我有一个界面

interface Employee {
   name: string
}

在将其保存到数据库中后,我想要一个扩展版本:

interface EmployeeDb {
   id: string,
   name: string
}

我想在处理检查时区分它,以便在我的存储中保存数据后,类型检查器不会抱怨没有 id 值。 意思是我想避免使用这个:

interface Employee {
   id?: string,
   name: string
}

所以我不必到处检查身份证。

所以我想这样做:

type Employee = {
   name: string
}

type IDatabaseObject<T> = {
  id: IDatabaseObjectId;
  [P in keyof T]: T[P];
};

type EmployeeDb = IDatabaseObject<Employee>

其中 IDE 给出了顶级语法的错误

计算属性名称必须是“string”、“number”、“symbol”或“any”类型。ts(2464)

所以我尝试使用接口并扩展它

interface IDatabaseObject { 
   id: string
}

interface EmployeeDb extends Employee, IDatabaseObject {}

但是在后端代码中,当我尝试使用此设置时,我再次从 vscode eslint 收到错误。 我这里有一个小代码,将数据添加到 localstorage,生成一个 id 并返回数据。 见代码:

class DbAsyncStorageTemplate<
    InputDataType,
    OutputDataType extends IDatabaseObject
> {

    async addEntry(object: InputDataType): Promise<OutputDataType> {

        const id: string = generateUuid()
        const dbObject = { id, ...object }
        dbObject.id = id

        // add the item to AsyncStorage directly
        await AsyncStorage.setItem(id, JSON.stringify(object))

        // ERROR HERE: return the new object
        return dbObject as OutputDataType
    } 
    }
}

但我从最后一行的 IDE (eslint) 中收到错误

类型转换 '{ id: string; } & InputDataType' 键入 'OutputDataType' 可能是错误的,因为两种类型都没有充分重叠。 如果这是故意的,请先将表达式转换为“未知”。 '{ id: 字符串; & InputDataType' 可分配给 'OutputDataType' 类型的约束,但 'OutputDataType' 可以用约束 'any' 的不同子类型实例化。

关于如何正确执行此操作的任何建议?

我想你正在寻找这个: https://www.typescriptlang.org/docs/handbook/advanced-types.html#:~:text=an%20intersection%20type%3A-,//%20Use%20this%3A ,%7D,-尝试

您正在尝试基于旧类型(例如 Employee;或一般情况下的 T)创建新类型 (IDatabaseObject)。 这是一个映射类型。

在你的代码中,

[P in keyof T]: T[P]

返回您的旧类型而不是该旧类型的成员。 因此,您需要关闭大括号并将其与您要添加的任何其他新成员相交。

即为 IDatabseObject 执行以下操作

type IDatabaseObject<T> = {
    id: number;
} & {
    [P in keyof T]: T[P];
};

我相信您正在寻找类型的交集

type Employee = {
   name: string
}

type EmployeeDb = {
  id: string;
} & Employee;

您还可以定义原始数据库接口并根据需要使用PickOmit实用程序。

选择实用程序

interface Todo {
  title: string;
  description: string;
  completed: boolean;
}

type TodoPreview = Pick<Todo, "title" | "completed">;

const todo: TodoPreview = {
  title: "Clean room",
  completed: false,
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM