I need to create a type which excludes certain literal types and accepts every other string. I tried this:
type ExcludedKeys = "a"|"b"
type MyType = {
[K in Exclude<string,ExcludedKeys>]: any
}
const obj: MyType = {
a: 0, // No Error
b: 1 // No Error
}
But soon I found out that Exclude<string,ExcludedKeys> simply evaluates to string and it's not possible to do it this way. Then I have tried this 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 wanted error.
}
const obj: MyType<Obj> = {
a: 0, // No Error
b: 1, // No Error
c: 3
}
but this only works when members of ExcludedKeys are the only props of the object.
What I need
As said, a type that negates those property names assignable to a set of string
type ExcludedKeys = "a"|"b"
const obj = {
a: 0, // Error Here
b: 1, // Error Here
c: 3
}
Edit
Even though I didn't mention it to simplify the context, as jsejcksn's answer pointed out, I needed this type to preserve type info from a given class model. With that said, lepsch's answer remains the accepted one because it does just what I asked for in the most short and simple way. Anyway, I'd like to share how I changed that approach to suit my needs.
type ExcludedKeys = "a"|"b"
type MyType<T> = {
[K in keyof T]: T[K]
} & {
[K in ExcludedKeys]?: never
}