Typescript: сопоставленный тип, чтобы сделать каждое свойство доступным только для чтения, кроме выбранных свойств. - PullRequest
0 голосов
/ 17 февраля 2020

Я столкнулся с проблемой, когда не хотел переписывать несколько интерфейсов.

Мне нужен один интерфейс для полной записи, а также «копия» этого интерфейса, где все поля доступны только для чтения. кроме тех, которые я выбираю для записи.

В Typescript есть сопоставленные типы, которые могут это разрешать.

Ответы [ 2 ]

0 голосов
/ 17 февраля 2020

Мы можем достичь этого, используя некоторые типы утилит или напрямую сопоставленные типы. Рассмотрим следующее:

type MakeSomePropsReadonly<A, K extends keyof A> = Readonly<Pick<A, K>> & Omit<A, K>

type Original = {
    a: string,
    b: number,
    c: boolean
}
type Example = MakeSomePropsReadonly<Original, 'a'>
const example: Example  = {
    a: 'a',
    b: 1,
    c: true
}

example.a = 'b'; // error a property is readonly
example.b = 2; // ok it is not readonly

Что делает наш тип Readonly<Pick<A, K>> & Omit<A, K>:

  • Readonly<Pick<A, K>> - создает тип, который имеет только ключи, выбранные K, и все все только для чтения , В результате мы получаем только часть типа, которая имеет только эти ключи, которые мы выбираем
  • & Omit<A, K> мы пересекаем предыдущий сопоставленный типизированный со свойствами только для чтения со второй частью, поэтому Omit<A, K> создаст объект, который будет иметь все поля с ключом, отличным от K

Итак, мы создаем тип, объединяя один тип со всеми свойствами только для чтения с другим с записываемыми.


Мы также можем сделайте это по-другому, поэтому у нас есть интерфейс «только для чтения», когда вы описываете и выбираете, какие поля доступны для записи:

type MakeSomePropsWritable<A, K extends keyof A> = {
    -readonly [Key in K]: A[Key]
} & Omit<A, K>

type Original = {
    readonly a: string,
    readonly b: number,
    readonly c: boolean
}
type Example = MakeSomePropsWritable<Original, 'a'>
const example: Example  = {
    a: 'a',
    b: 1,
    c: true
}

example.a = 'b'; // this is now ok as we left it writable
example.b = 2; // this is an error as expected

В этой реализации нет ничего другого, кроме:

  • -readonly [Key in K]: A[Key] - мы говорим, что удаляем readonly из этих полей с префиксом -
0 голосов
/ 17 февраля 2020
export type DeepReadOnly<T> = { readonly [key in keyof T]: DeepReadOnly<T[key]> };
export type DeepMutable<T> = { -readonly [key in keyof T]: DeepMutable<T[key]> };
export type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
export type DeepKeepMutable<T, K extends keyof T> = DeepReadOnly<Omit<T, K>> & DeepMutable<Pick<T, K>>;

// use as follows
let o: DeepKeepMutable<Metadata, 'time' | 'payload'>;
// this will keep time and payload writeable while the rest are readonly

// it is also possible to extend and modify these types with index signatures, optional properties and level of depth

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...