在这个挑战中,你可以使用任意你喜欢的方式实现这个类型 - Interface, Type 或 Class 都行。你需要提供两个函数 option(key, value) 和 get()。在 option 中你需要使用提供的 key 和 value 扩展当前的对象类型,通过 get 获取最终结果
例如:
declare const config: Chainableconst result = config .option('foo', 123) .option('name', 'type-challenges') .option('bar', { value: 'Hello World' }) .get()// 期望 result 的类型是:interface Result { foo: number name: string bar: { value: string }}
你只需要在类型层面实现这个功能 - 不需要实现任何 TS/JS 的实际逻辑
你可以假设 key 只接受字符串而 value 接受任何类型,你只需要暴露它传递的类型而不需要进行任何处理。同样的 key 只会被使用一次
答案
type Chainable<T = {}> = { option<K extends string, V>( key: K extends keyof T ? never : K, value: V ): Chainable<Omit<T,K> & Record<K, V>> get(): T}
上面方法保证了相同的 key 只能调用 option 一次,如果题目改成相同 key 可覆盖的话:
type Chainable<T = {}> = { option<K extends string, V>( key: K extends keyof T ? V extends T[K] ? never : K : K, value: V ): Chainable<Omit<T,K> & Record<K, V>> get(): T}