[Typescript] 17. Medium - Readonly 2
typescript 17 Medium readonly
2023-09-14 08:59:12 时间
Implement a generic MyReadonly2<T, K>
which takes two type argument T
and K
.
K
specify the set of properties of T
that should set to Readonly. When K
is not provided, it should make all properties readonly just like the normal Readonly<T>
.
For example
interface Todo {
title: string
description: string
completed: boolean
}
const todo: MyReadonly2<Todo, 'title' | 'description'> = {
title: "Hey",
description: "foobar",
completed: false,
}
todo.title = "Hello" // Error: cannot reassign a readonly property
todo.description = "barFoo" // Error: cannot reassign a readonly property
todo.completed = true // OK
/* _____________ Your Code Here _____________ */
// 1. Make all the props as readonly
// 2. & the prop not in K without readonly
// 3. K: set default value as keyof T, and should extends keyof T
type MyReadonly2<T, K extends keyof T = keyof T> = {
readonly [P in keyof T]: T[P]
} & {
[P in keyof T as P extends K ? never: P]: T[P]
}
type x = keyof Todo2
/* _____________ Test Cases _____________ */
import type { Alike, Expect } from '@type-challenges/utils'
type cases = [
Expect<Alike<MyReadonly2<Todo1>, Readonly<Todo1>>>,
Expect<Alike<MyReadonly2<Todo1, 'title' | 'description'>, Expected>>,
Expect<Alike<MyReadonly2<Todo2, 'title' | 'description'>, Expected>>,
]
// @ts-expect-error
type error = MyReadonly2<Todo1, 'title' | 'invalid'>
interface Todo1 {
title: string
description?: string
completed: boolean
}
interface Todo2 {
readonly title: string
description?: string
completed: boolean
}
interface Expected {
readonly title: string
readonly description?: string
completed: boolean
}
Step by step:
1. Make all prop as readonly
type MyReadonly2<T, K extends keyof T = keyof T> = {
readonly [P in keyof T]: T[P]
}
type x = MyReadonly2<Todo1, 'title' | 'description'>
/*
type x = {
readonly title: string;
readonly description?: string | undefined;
readonly completed: boolean;
}
*/
2. For prop not in K, make as not readonly
type MyReadonly2<T, K extends keyof T = keyof T> = {
[P in keyof T as P extends K ? never: P]: T[P]
}
type x = MyReadonly2<Todo1, 'title' | 'description'>
/*
type x = {
completed: boolean;
}
*/
3. Do intersection:
type MyReadonly2<T, K extends keyof T = keyof T> = {
readonly [P in keyof T]: T[P]
} & {
[P in keyof T as P extends K ? never: P]: T[P]
}
4. K extends keyof T = keyof T
set default value of K as keyof T
if not defined and K should extends keyof T
相关文章
- [Typescript] 89. Hard - Currying 1
- [Typescript] export = and import = require()
- [Typescript] Convert a js project to typescript
- [Typescript] Recursive types (JSONValue)
- [TypeScript] Labelled tuple type
- [TypeScript] Make typescript stick - 2
- [React Typescript 2022] Type React hooks
- [Typescript] Create Type From Any Given Data in TypeScript
- [Typescript] Ignore Null or Undefined Values with TypeScript Non-Null Assertion Operator
- [TypeScript] Type check JavaScript files using JSDoc and Typescript 2.5
- [Typescript] Generics using TypeScript
- [Typescript Challenges] 144 Hard - Transpose
- [Typescript 4.9] TypeScript 4.9: satisfies operator
- [Typescript] 132. Medium - Filter
- [Typescript] 35. Medium - Absolute
- [Typescript] Definite assignment operator
- [TypeScript] Typescript Intersection & Union Types
- [React Typescript 2022] Use TypeScript to Type a React Class Component
- [Typescript] Create Type From Any Given Data in TypeScript
- [Typescript] Ignore Null or Undefined Values with TypeScript Non-Null Assertion Operator
- [Typescript Kaop-ts] Use AOP in Vue Components with TypeScript and Kaop-ts