Skip to content

Partial<T> make only some properties optional #25760

Closed

Description

Search Terms

Suggestion

Use Cases

current Partial<T> will make all properties of T optional
I want to specify only some properties of T optional

Examples

interface Message {
    mid: number;
    content: string;
}

interface MessageOptional {
   mid?: number;
   content: string;
}

const message: Message = assembleMessage({ content: 'hello' })

function assembleMessage(message: MessageOptional) : Message{
    const mid =  ... // generate mid somehow
    message.mid = mid
    return message
} 

it's very often sometimes we want to omit some properties of an object and later supplement it.
currently typescript has concepts like Intersection、Union, how about Complement?

Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript / JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. new expression-level syntax)

Activity

  1. 0x414c commented on Jul 18, 2018

    @0x414c

    You can use existing Partial and Exclude to implement an approach like this:

    type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
    type WithOptional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
    
    interface Foo {
        foo: string;
        bar: number;
        baz: boolean;
    }
    // { foo?: string; bar: number; baz?: boolean; }
    type OptionalFoo = WithOptional<Foo, 'foo' | 'baz'>;
    
    const createFoo = (base: OptionalFoo): Foo => {
      return { foo: 'foo', baz: true, ...base };
    };
    const optionalFoo: OptionalFoo = { foo: '???', bar: 2 };
    const fullFoo = createFoo(optionalFoo); // { foo: '???', bar: 2, baz: true }
  2. typescript-bot commented on Jul 30, 2018

    @typescript-bot
    Contributor

    Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.

  3. kacluk123 commented on Mar 16, 2020

    @kacluk123

    Guys those solutions are unredable. I think it's better to create separate interface.

  4. gr2m commented on Apr 16, 2020

    @gr2m

    This works for me

    type Optional<T, K extends keyof T> = Omit<T, K> & Partial<T>;

    Playground link

  5. ftzi commented on Oct 7, 2020

    @ftzi

    This works for me

    type Optional<T, K extends keyof T> = Omit<T, K> & Partial<T>;

    Playground link

    This is really good. However, is there a way to keep the keys ordered as the original type?

  6. rattrayalex commented on Jul 27, 2021

    @rattrayalex

    type-fest has SetOptional, for those who would rather npm install --dev utilities like this.

  7. b-steel commented on Aug 26, 2021

    @b-steel

    Alex Rattray (@rattrayalex) Thank you! This has all that I could need and more

  8. mfuatnuroglu commented on Aug 27, 2021

    @mfuatnuroglu

    type onlyOneRequired = Partial<Tag> & {id: string}
    In the above type all properties of Tag are optional instead id which is required.

  9. tresorama commented on Sep 19, 2022

    @tresorama

    Edited on 2023-09-06:
    The PartialWithRequired present here will not convert property declared as optional (like daz?: string) as required. In case is what you need use the great code of Peter W (@techieshark) of this comment


    In case you need to ensurethat All prop are optional but some of those are required this worked for me (Thanks to Gregor Martynus (@gr2m) for the starting point.)

    // All props are required but some are optional
    type Optional<T, K extends keyof T> = Omit<T, K> & Partial<T>;
    
    type Test = {
      foo: string;
      bar: string;
      baz: string;
      daz?: string;
    };
    type Test1 = Optional<Test, "foo">;
    const test1: Test1 = {
      bar: '',
      baz: ''
    }
    type Test2 = Optional<Test, "bar" | "baz">;
    const test2: Test2 = {
      foo: ''
    }
    
    
    // All prop are optional but some of those are required
    type PartialWithRequired<T, K extends keyof T> = Pick<T, K> & Partial<T>;
    
    type Test3 = PartialWithRequired<Test, 'bar' | 'foo'>;
    const test3:Test3 = {
      bar: '',
      foo: ''
    }

    Playground

  10. techieshark commented on Sep 6, 2023

    @techieshark

    Jacopo Marrone (@tresorama) thanks for that starting point. It seems that since type Test already requires all properties but one (daz?), the code provided works.

    But if starting out with optional properties and we want to actually make them required, we can also use the Required<> utility. Here's this:

    type Test = {
      foo?: string;
      bar?: string;
      baz: string;
    };
    
    // All prop are optional but some of those are required -- NOTE! doesn't work, see Test1.
    type PartialWithRequired<T, K extends keyof T> = Pick<T, K> & Partial<T>;
    
    type Test1 = PartialWithRequired<Test, 'foo'|'bar'>;
    // @ts-expect-error since `Pick` from `PartialWithRequired` does NOT mark an optional parameter like 'foo' or 'bar' as required
    const test1:Test1 = {}
    
    // Actually works:
    type PartialExceptTheseRequired<T, K extends keyof T> = Pick<Required<T>, K> & Partial<T>
    
    type Test2 = PartialExceptTheseRequired<Test, 'foo'|'bar'>
    const test2:Test2 = {}
    // ^ it errors, which we want, since we are now requiring foo and bar but haven't set them.

    Playground

  11. tresorama commented on Sep 6, 2023

    @tresorama

    Peter W (@techieshark) Fantastic!
    I didn't know Required

  12. locked as resolved and limited conversation to collaborators on Oct 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    QuestionAn issue which isn't directly actionable in code

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions