Typescript: Proposal: Mapped Types syntax to remove modifiers

Created on 27 Jan 2017  路  6Comments  路  Source: microsoft/TypeScript



Current TypeScript Version: 2.1.1

We have a syntax to add "readonly" to every property of a type. Unfortunately, it seems there is no way to have the reverse operation: removing it.
This is useful for creating Mocked version of types for UTs, which have readonly fields in production.

This should work recursively.

Code

interface MyType2 {
  readonly z1: number;
  z2: string;
}

interface MyType {
  readonly a: number;
  readonly b: MyType2;
  c: string;
  d: MyType2;
}

type Mock<T> {
  [P in keyofwithoutmodifiers T]: Mock<T[P]>;
}

type MyMockedType = Mock<MyType>;

Expected behavior:
type MyMockedType to be

{
  a: number;
  b: { z1: number; z2: string };
  c: string;
  d: { z1: number; z2: string };
}

Actual behavior:
not possible right now

Fixed Suggestion

Most helpful comment

I do not think we will be adding yet another construct to remove readonly and optionality in mapped types; we have a limited budget of complexity and every new concept comes in with its cost both for language users and maintainers.

You can do this today by breaking the homomorphic relationship between the target of the map and the result; to do so you need to disassociate the key from the type. e.g.:

type Mutable<T extends { [x: string]: any }, K extends string> = {
    [P in K]: T[P];
}

type Mock<T> = Mutable<T, keyof T>;

All 6 comments

I do not think we will be adding yet another construct to remove readonly and optionality in mapped types; we have a limited budget of complexity and every new concept comes in with its cost both for language users and maintainers.

You can do this today by breaking the homomorphic relationship between the target of the map and the result; to do so you need to disassociate the key from the type. e.g.:

type Mutable<T extends { [x: string]: any }, K extends string> = {
    [P in K]: T[P];
}

type Mock<T> = Mutable<T, keyof T>;

@mhegazy your code example is a solution if you want to transform

interface TypeA {
  readonly name: string;
}

to

interface TypeB {
  name: string;
}

But if you have

interface TypeA {
  readonly name: string;
  readonly color?: string;
}

and this would transform it to this

interface TypeB {
  name: string;
  color: string;
}

which is more then just removing the modifiers.

In combination with Partial<T> it is possible to remove all modifiers and make everything optional or make everything required but is isn't possible to just remove the modifiers and keep the original mix of required and optional fields or is it?

it is possible to remove all modifiers and make everything optional or make everything required but is isn't possible to just remove the modifiers and keep the original mix of required and optional fields or is it?

No; we will need to add a new mutable/readwrite modifier to undo the readonly modifier effect. but as i noted earlier, there is limited budget to adding concepts in the language.

I think this was fixed by #21919.

It definitely appears that way. The following works for me:

type Mutable<T> = {
    -readonly [P in keyof T]: T[P];
};

What if I want to remove the "private" keyword?

Was this page helpful?
0 / 5 - 0 ratings