I want to be able to create a new type DataObject that simply omits the id property of an interface that extends the Model interface. DataObject should therefore require all properties of T, except for id, and prohibit any other properties. I have the following types/interfaces defined:
type DataObject<T extends Model> = Omit<T, "id">
interface Model extends JSONObject {
id: string
}
interface JSONObject {
[key: string]: JSONValue
}
type JSONArray = JSONValue[]
type JSONValue = PrimitiveValue | JSONObject | JSONArray
type PrimitiveValue = string | number | boolean
Then I have several functions that accept data objects of a given type and inserts the data into a database, in a similar pattern to this:
// identifier is the table name, optionally with the id provided "tablename:id"
function insert<T extends Model>(identifier: string, data: DataObject<T>) {
//...inserts data
}
But, when I use the function, it does not enforce the typing I want it to; I want it to give an error if I try to give it a data object containing any properties not defined in a given interface that extends Model, (except for id), and if it is missing any properties (except for id).
interface Person extends Model {
name: string,
age: number
}
// this should not be valid
insert<Person>({
foo: "bar",
id: "a1b2"
})
// This should not be valid either
const personData: DataObject<Person>{
name: "John",
id: "12345"
}
If DataObject simply takes any type T it works, but I want it to specifically be an extension of Model. Is this possible somehow?
Some more context: The reason why I want id to be excluded when inserting data is that the database takes care of creating the record id, but when retrieving records from the database the id property is present, hence why Model always has it.
I've tried defining my own Omit type and using it instead. Also tried defining the DataObject type directly in the function definiton.