feat: two more challenges

This commit is contained in:
Anthony Fu 2020-07-26 02:28:55 +08:00
parent 09984c07cf
commit df6f2b30e9
15 changed files with 124 additions and 5 deletions

View File

@ -34,7 +34,7 @@ English | <a href='./README.zh-CN.md'>简体中文</a>
> Click the following badges to see detail of the challenges!
<!--challenges-start-->
<a href="./questions/2-medium-return-type/README.md" target="_blank"><img src="https://img.shields.io/badge/-%232%E3%83%BBGet%20Return%20Type-d8af2c" alt="#2・Get Return Type"/></a> <a href="./questions/3-medium-omit/README.md" target="_blank"><img src="https://img.shields.io/badge/-%233%E3%83%BBOmit%3CT%2C%20K%3E-d8af2c" alt="#3・Omit<T, K>"/></a> <a href="./questions/4-easy-pick/README.md" target="_blank"><img src="https://img.shields.io/badge/-%234%E3%83%BBPick%3CT%2C%20K%3E-green" alt="#4・Pick<T, K>"/></a> <a href="./questions/5-hard-readonly-keys/README.md" target="_blank"><img src="https://img.shields.io/badge/-%235%E3%83%BBGet%20Readonly%20Keys-red" alt="#5・Get Readonly Keys"/></a> <a href="./questions/6-extreme-simple-vue/README.md" target="_blank"><img src="https://img.shields.io/badge/-%236%E3%83%BBSimple%20Vue-purple" alt="#6・Simple Vue"/></a>
<a href="./questions/2-medium-return-type/README.md" target="_blank"><img src="https://img.shields.io/badge/-%232%E3%83%BBGet%20Return%20Type-d8af2c" alt="#2・Get Return Type"/></a> <a href="./questions/3-medium-omit/README.md" target="_blank"><img src="https://img.shields.io/badge/-%233%E3%83%BBOmit%3CT%2C%20K%3E-d8af2c" alt="#3・Omit<T, K>"/></a> <a href="./questions/4-easy-pick/README.md" target="_blank"><img src="https://img.shields.io/badge/-%234%E3%83%BBPick%3CT%2C%20K%3E-green" alt="#4・Pick<T, K>"/></a> <a href="./questions/5-hard-readonly-keys/README.md" target="_blank"><img src="https://img.shields.io/badge/-%235%E3%83%BBGet%20Readonly%20Keys-red" alt="#5・Get Readonly Keys"/></a> <a href="./questions/6-extreme-simple-vue/README.md" target="_blank"><img src="https://img.shields.io/badge/-%236%E3%83%BBSimple%20Vue-purple" alt="#6・Simple Vue"/></a> <a href="./questions/7-easy-readonly/README.md" target="_blank"><img src="https://img.shields.io/badge/-%237%E3%83%BBReadonly%3CT%3E-green" alt="#7・Readonly<T>"/></a> <a href="./questions/8-medium-readonly-2/README.md" target="_blank"><img src="https://img.shields.io/badge/-%238%E3%83%BBReadonly%202-d8af2c" alt="#8・Readonly 2"/></a>
<!--challenges-end-->
</details>

View File

@ -28,7 +28,7 @@ TypeScript 类型体操姿势合集
> 点击下方徽章查看挑战内容
<!--challenges-start-->
<a href="./questions/2-medium-return-type/README.zh-CN.md" target="_blank"><img src="https://img.shields.io/badge/-%232%E3%83%BB%E8%8E%B7%E5%8F%96%E5%87%BD%E6%95%B0%E8%BF%94%E5%9B%9E%E7%B1%BB%E5%9E%8B-d8af2c" alt="#2・获取函数返回类型"/></a> <a href="./questions/3-medium-omit/README.md" target="_blank"><img src="https://img.shields.io/badge/-%233%E3%83%BB%E5%AE%9E%E7%8E%B0%20Omit%3CT%2C%20K%3E-d8af2c" alt="#3・实现 Omit<T, K>"/></a> <a href="./questions/4-easy-pick/README.md" target="_blank"><img src="https://img.shields.io/badge/-%234%E3%83%BB%E5%AE%9E%E7%8E%B0%20Pick%3CT%2C%20K%3E-green" alt="#4・实现 Pick<T, K>"/></a> <a href="./questions/5-hard-readonly-keys/README.md" target="_blank"><img src="https://img.shields.io/badge/-%235%E3%83%BB%E8%8E%B7%E5%8F%96%E5%8F%AA%E8%AF%BB%E5%AD%97%E6%AE%B5-red" alt="#5・获取只读字段"/></a> <a href="./questions/6-extreme-simple-vue/README.md" target="_blank"><img src="https://img.shields.io/badge/-%236%E3%83%BB%E7%AE%80%E5%8D%95%E7%9A%84%20Vue%20%E7%B1%BB%E5%9E%8B-purple" alt="#6・简单的 Vue 类型"/></a>
<a href="./questions/2-medium-return-type/README.zh-CN.md" target="_blank"><img src="https://img.shields.io/badge/-%232%E3%83%BB%E8%8E%B7%E5%8F%96%E5%87%BD%E6%95%B0%E8%BF%94%E5%9B%9E%E7%B1%BB%E5%9E%8B-d8af2c" alt="#2・获取函数返回类型"/></a> <a href="./questions/3-medium-omit/README.md" target="_blank"><img src="https://img.shields.io/badge/-%233%E3%83%BB%E5%AE%9E%E7%8E%B0%20Omit%3CT%2C%20K%3E-d8af2c" alt="#3・实现 Omit<T, K>"/></a> <a href="./questions/4-easy-pick/README.md" target="_blank"><img src="https://img.shields.io/badge/-%234%E3%83%BB%E5%AE%9E%E7%8E%B0%20Pick%3CT%2C%20K%3E-green" alt="#4・实现 Pick<T, K>"/></a> <a href="./questions/5-hard-readonly-keys/README.md" target="_blank"><img src="https://img.shields.io/badge/-%235%E3%83%BB%E8%8E%B7%E5%8F%96%E5%8F%AA%E8%AF%BB%E5%AD%97%E6%AE%B5-red" alt="#5・获取只读字段"/></a> <a href="./questions/6-extreme-simple-vue/README.md" target="_blank"><img src="https://img.shields.io/badge/-%236%E3%83%BB%E7%AE%80%E5%8D%95%E7%9A%84%20Vue%20%E7%B1%BB%E5%9E%8B-purple" alt="#6・简单的 Vue 类型"/></a> <a href="./questions/7-easy-readonly/README.md" target="_blank"><img src="https://img.shields.io/badge/-%237%E3%83%BB%E5%AE%9E%E7%8E%B0%20Readonly%3CT%3E-green" alt="#7・实现 Readonly<T>"/></a> <a href="./questions/8-medium-readonly-2/README.md" target="_blank"><img src="https://img.shields.io/badge/-%238%E3%83%BBReadonly%202-d8af2c" alt="#8・Readonly 2"/></a>
<!--challenges-end-->
## 参与贡献

View File

@ -1,5 +1,5 @@
<!--info-header-start-->
# Omit<T, K> <img src="https://img.shields.io/badge/-medium-d8af2c" alt="medium"/>
# Omit\<T, K\> <img src="https://img.shields.io/badge/-medium-d8af2c" alt="medium"/>
> by Anthony Fu
<a href="https://type-challenges.netlify.app/case/3/play/en" target="_blank"><img src="https://img.shields.io/badge/-Take%20the%20Challenge-blue?logo=typescript" alt="Take the Challenge"/></a> <!--info-header-end-->

View File

@ -1,5 +1,5 @@
<!--info-header-start-->
# Pick<T, K> <img src="https://img.shields.io/badge/-easy-green" alt="easy"/>
# Pick\<T, K\> <img src="https://img.shields.io/badge/-easy-green" alt="easy"/>
> by Anthony Fu
<a href="https://type-challenges.netlify.app/case/4/play/en" target="_blank"><img src="https://img.shields.io/badge/-Take%20the%20Challenge-blue?logo=typescript" alt="Take the Challenge"/></a> <!--info-header-end-->

View File

@ -0,0 +1,31 @@
<!--info-header-start-->
# Readonly\<T\> <img src="https://img.shields.io/badge/-easy-green" alt="easy"/>
> by Anthony Fu
<a href="https://type-challenges.netlify.app/case/7/play/en" target="_blank"><img src="https://img.shields.io/badge/-Take%20the%20Challenge-blue?logo=typescript" alt="Take the Challenge"/></a> <!--info-header-end-->
Implement the built-in `Readonly<T>` generic without using it.
Constructs a type with all properties of T set to readonly, meaning the properties of the constructed type cannot be reassigned.
For example
```ts
interface Todo {
title: string
description: string
}
const todo: MyReadonly<Todo> = {
title: "Hey",
description: "foobar"
}
todo.title = "Hello" // Error: cannot reassign a readonly property
todo.description = "barFoo" // Error: cannot reassign a readonly property
```
<!--info-footer-start-->
<a href="../../README.md" target="_blank"><img src="https://img.shields.io/badge/-Back-grey" alt="Back"/></a> <a href="https://type-challenges.netlify.app/case/7/answers" target="_blank"><img src="https://img.shields.io/badge/-Check%20out%20Answers-F59BAF?logo=awesome-lists&logoColor=white" alt="Check out Answers"/></a>
<!--info-footer-end-->

View File

@ -0,0 +1,8 @@
title: Readonly<T>
author:
name: Anthony Fu
email: hi@antfu.me
github: antfu
tags: built-in, readonly, object-keys

View File

@ -0,0 +1 @@
title: 实现 Readonly<T>

View File

@ -0,0 +1 @@
type MyReadonly<T> = any

View File

@ -0,0 +1,11 @@
import { Equal, Expect } from '@type-challenges/utils'
type cases = [
Expect<Equal<MyReadonly<Todo1>, Readonly<Todo1>>>,
]
interface Todo1 {
title: string
description: string
completed: boolean
}

View File

@ -0,0 +1,33 @@
<!--info-header-start-->
# Readonly 2 <img src="https://img.shields.io/badge/-medium-d8af2c" alt="medium"/>
> by Anthony Fu
<a href="https://type-challenges.netlify.app/case/8/play/en" target="_blank"><img src="https://img.shields.io/badge/-Take%20the%20Challenge-blue?logo=typescript" alt="Take the Challenge"/></a> <!--info-header-end-->
Implement a generic `MyReadonly2<T, K>` which takes two type argument `T` and `K`.
`K` specify the set of properties if `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
```ts
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
```
<!--info-footer-start-->
<a href="../../README.md" target="_blank"><img src="https://img.shields.io/badge/-Back-grey" alt="Back"/></a> <a href="https://type-challenges.netlify.app/case/8/answers" target="_blank"><img src="https://img.shields.io/badge/-Check%20out%20Answers-F59BAF?logo=awesome-lists&logoColor=white" alt="Check out Answers"/></a>
<!--info-footer-end-->

View File

@ -0,0 +1,8 @@
title: Readonly 2
author:
name: Anthony Fu
email: hi@antfu.me
github: antfu
tags: readonly, object-keys

View File

@ -0,0 +1 @@
title: Readonly 2

View File

@ -0,0 +1 @@
type MyReadonly2<T, K> = any

View File

@ -0,0 +1,18 @@
import { Equal, Expect } from '@type-challenges/utils'
type cases = [
Expect<Equal<MyReadonly2<Todo1>, Readonly<Todo1>>>,
Expect<Equal<MyReadonly2<Todo1, 'title' | 'description'>, Expected>>,
]
interface Todo1 {
title: string
description?: string
completed: boolean
}
interface Expected {
readonly title: string
readonly description?: string
completed: boolean
}

View File

@ -13,6 +13,12 @@ const DifficultyColors: Record<string, string> = {
extreme: 'purple',
}
function escape(text: string) {
return text
.replace(/</, '\\<')
.replace(/>/, '\\>')
}
function toBadgeURL(label: string, text: string, color: string, args = '') {
return `https://img.shields.io/badge/${encodeURIComponent(label.replace(/-/g, '--'))}-${encodeURIComponent(text.replace(/-/g, '--'))}-${color}${args}`
}
@ -42,7 +48,7 @@ async function insertInfoReadme(filepath: string, quiz: Quiz, locale: keyof type
.replace(
/<!--info-header-start-->[\s\S]*<!--info-header-end-->/,
'<!--info-header-start-->\n'
+ `# ${info.title} ${toBadge('', quiz.difficulty, DifficultyColors[quiz.difficulty])}\n`
+ `# ${escape(info.title || '')} ${toBadge('', quiz.difficulty, DifficultyColors[quiz.difficulty])}\n`
+ `> by ${info.author?.name}\n\n`
+ toBadgeLink(toPlay(quiz.no, locale), '', messages[locale]['take-the-challenge'], 'blue', '?logo=typescript')
+ '<!--info-header-end-->',