current Partial<T>
will make all properties of T
optional
I want to specify only some properties of T
optional
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
?
My suggestion meets these guidelines:
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 }
@0x414c
thanks anyway, I hope Omit
and WithOptional
can be added to lib.d.ts in the future cause it's really a very common need.
yet there's another problem with keyof a Union type
interface MessageA {
mid: number;
type: number;
text: string;
}
interface MessageB {
mid: number;
type: number;
url: string;
}
type Message = MessageA | MessageB
type Keys = keyof Message // 'mid' | 'type'
/**
* {
* mid?: number;
* type: number;
* }
*/
type OptionalMessage = WithOptional<Message, 'mid'>
// what I really what :
type OptionalMessageNeed = WithOptional<MessageA, 'mid'> | WithOptional<MessageB, 'mid'>
I just got a solution.
type AllKeyOf<T> = T extends never ? never : keyof T
type Omit<T, K> = { [P in Exclude<keyof T, K>]: T[P] }
type Optional<T, K> = { [P in Extract<keyof T, K>]?: T[P] }
type WithOptional<T, K extends AllKeyOf<T>> = T extends never ? never : Omit<T, K> & Optional<T, K>
/**
{
mid?: number;
type: number;
text?: string;
}
| {
mid?: number;
type: number;
url: string;
}
*/
type a = WithOptional<Message, 'mid' | 'text'>
Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.
Guys those solutions are unredable. I think it's better to create separate interface.
This works for me
type Optional<T, K extends keyof T> = Omit<T, K> & Partial<T>;
This is really good. However, is there a way to keep the keys ordered as the original type?
Most helpful comment
This works for me
Playground link