最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - typescript extending types vs interfaces - Stack Overflow

programmeradmin2浏览0评论

This might a be relatively noob question, I have an interface

interface Employee {
   name: string
}

and I would like to have an extended version of this after it being saved into the DB:

interface EmployeeDb {
   id: string,
   name: string
}

I would like to differentiate it when handling checks so after saving data in my storage, the type checker won't plain about not having id value. Meaning I want to avoid using this:

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

so I don't have to check for id everywhere.

So I am trying to do it this way:

type Employee = {
   name: string
}

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

type EmployeeDb = IDatabaseObject<Employee>

which the IDE gives an error with the top syntax

A puted property name must be of type 'string', 'number', 'symbol', or 'any'.ts(2464)

so I tried to use interface and extend it

interface IDatabaseObject { 
   id: string
}

interface EmployeeDb extends Employee, IDatabaseObject {}

but in the backend code when I try to use this setup I get an error from vscode eslint again. I have a small code here that adds the data to localstorage, generates a id and returns the data. see code:

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
    } 
    }
}

but I get an error from the IDE (eslint) for the last line

Conversion of type '{ id: string; } & InputDataType' to type 'OutputDataType' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first. '{ id: string; } & InputDataType' is assignable to the constraint of type 'OutputDataType', but 'OutputDataType' could be instantiated with a different subtype of constraint 'any'.

any remendation on how to do this properly?

This might a be relatively noob question, I have an interface

interface Employee {
   name: string
}

and I would like to have an extended version of this after it being saved into the DB:

interface EmployeeDb {
   id: string,
   name: string
}

I would like to differentiate it when handling checks so after saving data in my storage, the type checker won't plain about not having id value. Meaning I want to avoid using this:

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

so I don't have to check for id everywhere.

So I am trying to do it this way:

type Employee = {
   name: string
}

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

type EmployeeDb = IDatabaseObject<Employee>

which the IDE gives an error with the top syntax

A puted property name must be of type 'string', 'number', 'symbol', or 'any'.ts(2464)

so I tried to use interface and extend it

interface IDatabaseObject { 
   id: string
}

interface EmployeeDb extends Employee, IDatabaseObject {}

but in the backend code when I try to use this setup I get an error from vscode eslint again. I have a small code here that adds the data to localstorage, generates a id and returns the data. see code:

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
    } 
    }
}

but I get an error from the IDE (eslint) for the last line

Conversion of type '{ id: string; } & InputDataType' to type 'OutputDataType' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first. '{ id: string; } & InputDataType' is assignable to the constraint of type 'OutputDataType', but 'OutputDataType' could be instantiated with a different subtype of constraint 'any'.

any remendation on how to do this properly?

Share Improve this question edited Jun 12, 2021 at 0:20 Armen Babakanian asked Jun 12, 2021 at 0:07 Armen BabakanianArmen Babakanian 2,3453 gold badges28 silver badges55 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 7

I believe you're looking for intersections of types.

type Employee = {
   name: string
}

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

You could also define the raw DB interface and use Pick or Omit utilities as needed.

Pick Utility

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

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

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

I think you are looking for this: https://www.typescriptlang/docs/handbook/advanced-types.html#:~:text=an%20intersection%20type%3A-,//%20Use%20this%3A,%7D,-Try

You are trying to create a new type (IDatabaseObject) based on an old type (Employee, for instance; or T, in the generic case). This is a Mapped Type.

In your code,

[P in keyof T]: T[P]

returns your old type rather than members of that old type. So you need to close the curly brackets and intersect it with any other new members you want to add.

i.e. do the following for IDatabseObject

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

评论列表(0)

  1. 暂无评论