designcise.com
What Does "-?" Mean in TypeScript?
<p>
Introduced in TypeScript 2.8, if the <code>?</code> modifier is prefixed with <code>-</code> (i.e. <code>-?</code>), it means that the <code>?</code> modifier is <em>removed</em> from a <a href="https://www.typescriptlang.org/docs/handbook/2/mapped-types.html" target="_blank">mapped type</a>, making all properties required.
</p>
<p class="note">
If the <code>?</code> modifier has <em>no</em> <a href="https://www.designcise.com/web/tutorial/what-does-plus-question-mark-mean-in-typescript" target="_blank"><code>+</code></a> or <code>-</code> prefix, then it is the same as if the <code>?</code> modifier was prefixed with <a href="https://www.designcise.com/web/tutorial/what-does-plus-question-mark-mean-in-typescript" target="_blank"><code>+</code></a> (i.e. <a href="https://www.designcise.com/web/tutorial/what-does-plus-question-mark-mean-in-typescript" target="_blank"><code>+?</code></a>).
</p>
<p>
For example, using "<code>-?</code>", the <a href="https://www.typescriptlang.org/docs/handbook/utility-types.html#requiredtype" target="_blank"><code>Required</code> utility type</a> can be implemented like so:
</p>
<pre>
type Required<Type> = { [Property in keyof Type]-?: Type[Property] };
</pre>
<p>
This maps all keys of type "<code>Type</code>" and makes them required.
</p>
<p>
You can, of course, make use of <code>-?</code> in various other ways. Consider for example the following, where the custom utility type takes all the properties from the type "<code>Type</code>" and changes their values to be required and be of type <code>string</code>:
</p>
<pre>
// TypeScript 2.8+
type RequestBody<Type> = {
[Property in keyof Type]-?: string;
};
</pre>
<p>
This could, for instance, be used like so:
</p>
<pre>
// TypeScript 2.8+
type Patient = {
name: string;
age?: number;
recovered?: boolean;
};
type PatientRequestBody = RequestBody<Patient>;
const patient: PatientRequestBody = {
name: 'John Doe',
age: '23',
recovered: 'false',
};
</pre>
<p>
If any property from the "<code>Patient</code>" type is missing or a value is <em>not</em> of type <code>string</code>, this would throw an error:
</p>
<pre>
// TypeScript 2.8+
// Error: Property 'recovered' is missing in type '{ name: string; age: string; }' but required in type 'RequestBody<Patient>'.
const <span class="wavy-error">patient</span>: PatientRequestBody = {
name: 'John Doe',
age: '23',
};
</pre>
<pre>
// TypeScript 2.8+
const patient: PatientRequestBody = {
name: 'John Doe',
age: '23',
// Error: Type 'boolean' is not assignable to type 'string'.
<span class="wavy-error">recovered</span>: false,
};
</pre>