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 badges2 Answers
Reset to default 7I 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];
};