How to omit optional properties from type?
Asked Answered
W

2

6

Given an object type that has optional properties, such as:

interface Person {
  name: string;
  age: number;
  friends?: Person[];
  jobName?: string;
}

… I'd like to remove all of its optional properties so that the result is:

interface Person {
  name: string;
  age: number;
}

How can I do that?


Please, note that I can't use Omit<Person, "friends" | "jobName"> because the actual properties are not known in advance. I have to somehow collect the union of keys of all optional properties:

type OptionalKey<Obj extends object> = {
  [Key in keyof Obj]: /* ... */ ? Key : never;
}[keyof Obj];

type PersonOptionalKey = OptionalKey<Person>;
// "friends" | "jobName"

Also, typescript remove optional property is poorly named and doesn't answer my question.

Wiles answered 5/7, 2021 at 13:56 Comment(1)
Something like this?Adcock
F
10

While the method proposed in the comments removes optional properties it also removes non-optional properties having undefined as a possible value of their type.

interface Person {
    required: string;
    optional?: string;
    maybeUndefined: string | undefined
}

/*
type A = { required: string }
*/
type A = ExcludeOptionalProps<Person>

In case you're looking for a helper type removing only optional keys you may write it as:

type RequiredFieldsOnly<T> = {
    [K in keyof T as T[K] extends Required<T>[K] ? K : never]: T[K]
}

playground link

Frugivorous answered 5/7, 2021 at 19:44 Comment(2)
I cant get RequiredFieldsOnly to work on [email protected], although it works in the playground. When I look at the intellisense it shows all the properties including the optional ones. Can you elaborate a bit on how the type works? I'm having a hard time wrapping my head around it.Zicarelli
My current understanding why it should work is the following: Required<T>[K] turns all optional fields of T to non optional, then if the original T[K] extends(is found on) Required<T>[K] then it's good to stay, otherwise it should be never. Seems correct, so why isn't working in my local project is beyond me.Zicarelli
J
0

https://www.typescriptlang.org/docs/handbook/2/mapped-types.html

// Removes 'optional' attributes from a type's properties
type Concrete<Type> = {
  [Property in keyof Type]-?: Type[Property];
};
 
type MaybeUser = {
  id: string;
  name?: string;
  age?: number;
};
 
type User = Concrete<MaybeUser>;

// results
type User = {
    id: string;
    name: string;
    age: number;
}

Edit: turns out Concrete just turns optional props to required props, it doesnt remove them.

better answer is here: https://mcmap.net/q/176852/-typescript-conditional-types-filter-out-readonly-properties-pick-only-required-properties

Jesseniajessey answered 19/8, 2022 at 19:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.