0

I would like to create a generic typescript type that omits any key-value pair from an input type where the value is of type unknown:

interface Foo {
  foo: string;
  bar: number;
  bla: unknown;
  baz: boolean;
}

type T = OmitUnknowns<Foo>;
// should be { foo: string; bar: number; baz: boolean; }

Is this possible? I'm struggling to figure it out because it seems like everything extends unknown in typescript...

DeX3
  • 5,200
  • 6
  • 44
  • 68
  • Does this answer your question? [Check if type is the unknown type](https://stackoverflow.com/questions/68232762/check-if-type-is-the-unknown-type) – Etheryte Feb 16 '23 at 12:29

1 Answers1

2

You can use a mapped type to remove the unknown properties (see here for how to test for unknown):

interface Foo {
    foo: string;
    bar: number;
    bla: unknown;
    baz: boolean;
}

type OmitUnknowns<T> = {
    [Key in keyof T as unknown extends T[Key] ? never : Key]: T[Key];
};

type T = OmitUnknowns<Foo>;

Playground link

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Beautiful, works like a charm! I saw the section about Key remapping via `as` in the typescript docs, but I'm confused - could you explain a bit what the `keyof T as unknown extends T[Key] ? never : Key` does? – DeX3 Feb 16 '23 at 16:11
  • @DeX3 - Basically, it says "For each `Key` in `keyof T`, if `unknown extends T[Key]`, use `never` for the key, otherwise use `Key` for the key." And if you use `never` as a key, the property is completely omitted from the resulting object type. In contrast, if we did `[Key in keyof T]: unknown extends T[Key] ? never : T[Key]` where we always take the key without doing anything to it, but convert the value to `never`, we'd end up with `bla: never` in the resulting object type. Mapping a key to `never` is *really* helpful for pruning object types. :-) – T.J. Crowder Feb 16 '23 at 17:25