My goal is to create a type that excludes certain literal types and accepts every other string. I initially attempted the following:
type ExcludedKeys = "a"|"b"
type MyType = {
[K in Exclude<string,ExcludedKeys>]: any
}
const obj: MyType = {
a: 0, // No Error
b: 1 // No Error
}
However, I discovered that Exclude<string,ExcludedKeys>
just simplifies to string
, making this method unfeasible. So, I tried another approach:
type ExcludedKeys = "a"|"b"
type MyType<T> = keyof T extends ExcludedKeys ? never : {
[K in keyof T]: T[K]
}
declare class Obj {
a: number
b: number
c: number // Adding this removes the desired error.
}
const obj: MyType<Obj> = {
a: 0, // No Error
b: 1, // No Error
c: 3
}
This method only works effectively when the members of ExcludedKeys
are the sole properties of the object.
What I'm Looking For
In simple terms, a type that prohibits assigning certain property names based on a set of strings.
type ExcludedKeys = "a"|"b"
const obj = {
a: 0, // Error Here
b: 1, // Error Here
c: 3
}
Edit
While I didn't mention it earlier to keep things concise, I require this type to retain the type information from a specific class model, as highlighted in jsejcksn's answer. Therefore, I have modified the approach suggested by lepsch to better suit my needs.
type ExcludedKeys = "a"|"b"
type MyType<T> = {
[K in keyof T]: T[K]
} & {
[K in ExcludedKeys]?: never
}