Reputation: 235
TypeScript's version is 3.2.1 and "tsconfig.json" is like below.
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"esModuleInterop": true
}
}
I'm looking for Partially "Partial" type in TypeScript.
type Entity = {
a: string,
b: string,
c?: string,
};
type Ham = MyType<Entity, 'b'>;
/**
* expected to equal
* {
* a: string,
* b?: string, // changed to be optional
* c?: string,
* };
*/
P.S. Titian and t7yang
Thank you for your replies. I checked your types then both types pass compiler's check!
const abc = { a: 'a', b: 'b', c: 'c' };
const ab = { a: 'a', b: 'b' };
const ac = { a: 'a', c: 'c' };
const a = { a: 'a' };
// by t7yang
let test1Abc: OptionalKey<Entity, 'b'> = abc;
let test1Ab: OptionalKey<Entity, 'b'> = ab;
let test1Ac: OptionalKey<Entity, 'b'> = ac;
let test1A: OptionalKey<Entity, 'b'> = a;
// by Titian Cernicova-Dragomir
let test2Abc: PickPartial<Entity, 'b'> = abc;
let test2Ab: PickPartial<Entity, 'b'> = ab;
let test2Ac: PickPartial<Entity, 'b'> = ac;
let test2A: PickPartial<Entity, 'b'> = a;
Upvotes: 19
Views: 7079
Reputation: 8550
Simple version of accepted answer (use Intersection of a Partial and Pick) without any intermediary types to confuse things:
type Entity = {
a: number,
b: number,
c?: number,
}
type Ham = Partial<Entity> & Pick<Entity, Exclude<keyof Entity, 'b'>>;
const b: Ham[] = [{ a: 1 }, { a: 1, b: 1 }, { a: 1, c: 1 }, { a: 1, b: 1, c: 1 }]; // OK.
const c: Ham = {}; // Bad.
Upvotes: 2
Reputation: 14474
Real simple solution:
type PickPartial<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
type PartialExcept<T, K extends keyof T> = Pick<T, K> & Partial<Omit<T, K>>;
Titian's solution was written before Typescript 3.5, which added the Omit helper.
Also remember that you can use string unions to pick multiple attributes to be made optional:
type Full = {
a: string;
b: string;
c: string;
}
// These are equivalent
type ARequired = PickPartial<Full, 'b' | 'c'>;
type ARequired = PartialExcept<Full, 'a'>;
Upvotes: 4
Reputation: 754
type Entity = {
a: string,
b: string,
c?: string,
};
type OptionalKey<T, O extends keyof T> = Pick<T, Exclude<keyof T, O>> & Partial<{ [P in O]: T[P] }>;
const a: OptionalKey<Entity, 'b'> = {
a: 'a',
}
const ab: OptionalKey<Entity, 'b'> = {
a: 'a',
b: 'b'
}
const ac: OptionalKey<Entity, 'b'> = {
a: 'a',
c: 'c'
}
The idea is pick all the properties that want to make optional, then merge with the type than we want to make the property optional.
You can check this in typescript playground
Upvotes: 2
Reputation: 249536
You can use Pick
in conjunction with Partial
to pick only the properties you want to make optional, while preserving the rest using Exclude
to get the keys excluding the ones passed in to make optional :
type Entity = {
a: string,
b: string,
c?: string,
};
type PickPartial<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>> & Partial<Pick<T, K>>
type Ham = PickPartial<Entity, 'b'>; // a, b? , c?
Upvotes: 15