awesome-typescript
                                
                                
                                
                                    awesome-typescript copied to clipboard
                            
                            
                            
                        「重学TS 2.0 」TS 练习题第七题
第七题
使用类型别名定义一个 EmptyObject 类型,使得该类型只允许空对象赋值:
type EmptyObject = {} 
// 测试用例
const shouldPass: EmptyObject = {}; // 可以正常赋值
const shouldFail: EmptyObject = { // 将出现编译错误
  prop: "TS"
}
在通过 EmptyObject 类型的测试用例检测后,我们来更改以下 takeSomeTypeOnly 函数的类型定义,让它的参数只允许严格SomeType类型的值。具体的使用示例如下所示:
type SomeType =  {
  prop: string
}
// 更改以下函数的类型定义,让它的参数只允许严格SomeType类型的值
function takeSomeTypeOnly(x: SomeType) { return x }
// 测试用例:
const x = { prop: 'a' };
takeSomeTypeOnly(x) // 可以正常调用
const y = { prop: 'a', addditionalProp: 'x' };
takeSomeTypeOnly(y) // 将出现编译错误
请在下面评论你的答案
7.1 EmptyObject
type EmptyObject = {
  // type PropertyKey = string | number | symbol
  [K in PropertyKey]: never 
}
// 测试用例
const shouldPass: EmptyObject = {}; // 可以正常赋值
const shouldFail: EmptyObject = { // 将出现编译错误
  prop: "TS"
}
7.2 takeSomeTypeOnly
type SomeType =  {
  prop: string
}
type Exclusive<T1, T2 extends T1> = {
  [K in keyof T2]: K extends keyof T1 ? T2[K] : never 
}
// 更改以下函数的类型定义,让它的参数只允许严格SomeType类型的值
function takeSomeTypeOnly<T extends SomeType>(x: Exclusive<SomeType, T>) { return x }
// 测试用例:
const x = { prop: 'a' };
takeSomeTypeOnly(x) // 可以正常调用
const y = { prop: 'a', addditionalProp: 'x' };
takeSomeTypeOnly(y) // 将出现编译错误
                                    
                                    
                                    
                                
type EmptyObject = {
    [P in PropertyKey]: never
}
// 测试用例
const shouldPass: EmptyObject = {}; // 可以正常赋值
const shouldFail: EmptyObject = { // 将出现编译错误
    prop: "TS"
}
type SomeType = {
    prop: string
}
type StrictType<T1 extends T2, T2> = {
    [P in keyof T1]: P extends keyof T2 ? T1[P] : never
}
// 更改以下函数的类型定义,让它的参数只允许严格SomeType类型的值
function takeSomeTypeOnly<T extends SomeType>(x: StrictType<T, SomeType>) { return x }
// 测试用例:
const x = { prop: 'a' };
takeSomeTypeOnly(x) // 可以正常调用
const y = { prop: 'a', addditionalProp: 'x' };
takeSomeTypeOnly(y) // 将出现编译错误
                                    
                                    
                                    
                                
// 使用类型别名定义一个 EmptyObject 类型,使得该类型只允许空对象赋值:
type EmptyObject = {
  [k in string | number | symbol]: never;
}
// 测试用例
const shouldPass: EmptyObject = {}; // 可以正常赋值
const shouldFail: EmptyObject = { // 将出现编译错误
  prop: "TS"
}
// 在通过 EmptyObject 类型的测试用例检测后,
// 我们来更改以下 takeSomeTypeOnly 函数的类型定义
// 让它的参数只允许严格SomeType类型的值。具体的使用示例如下所示:
type SomeType =  {
  prop: string
}
type OnlyTKeys<T, U extends T, K = keyof T> = {
  [k in keyof U]: k extends K ? U[k]: never;
}
// 更改以下函数的类型定义,让它的参数只允许严格SomeType类型的值
function takeSomeTypeOnly<T extends SomeType>(x: OnlyTKeys<SomeType, T>) { return x }
// 测试用例:
const x = { prop: 'a' };
takeSomeTypeOnly(x) // 可以正常调用
const y = { prop: 'a', addditionalProp: 'x' };
takeSomeTypeOnly(y) // 将出现编译错误
第一小题就是主动设置所有的属性对应的类型都是never,这样就只有空对象能满足要求。需要注意的是对象的索引类型是 string | number | symbol
第二小题和第一小题类似,只不过是要找到 SomeType 子类型上特有的属性,将其定义为 never。这样就相当于实现了对 SomeType 的严格匹配。
type SomeType = { prop: string; };
type OnlyKeys<T1, T2 extends T1> = { [K in keyof T2]: K extends keyof T1 ? T2[K] : never; };
// 更改以下函数的类型定义,让它的参数只允许严格SomeType类型的值 function takeSomeTypeOnly<T extends SomeType>(x: OnlyKeys<SomeType, T>) { return x; }
// 测试用例: const x = { prop: "a" }; takeSomeTypeOnly(x); // 可以正常调用
const y = { prop: "a", addditionalProp: "x" }; takeSomeTypeOnly(y); // 将出现编译错误
type EmptyObject = { [K in keyof any]: never }
// 测试用例 const shouldPass: EmptyObject = {}; // 可以正常赋值 const shouldFail: EmptyObject = { // 将出现编译错误 prop: "TS" }
// 只支持特定属性-必须完全匹配
type Tool<T> = { [K in keyof T] : T[K] }
type SomeType<T> = { [K in keyof T]: K extends 'prop' ? T[K] : never } type Res = Tool<SomeType<{prop: 'a', age: number}>>
// 更改以下函数的类型定义,让它的参数只允许严格SomeType类型的值 function takeSomeTypeOnly<T>(x: SomeType<T>) { return x }
// 测试用例: const x = { prop: 'a' }; takeSomeTypeOnly(x) // 可以正常调用
const y = { prop: 'a', addditionalProp: 'x' }; takeSomeTypeOnly(y) // 将出现编译错误
type Exclusive<T1, T2 extends T1> = { [K in keyof T2]: K extends keyof T1 ? T2[K] : never }
[K in keyof T2]: K extends keyof T1 ? T1[K] : never 为什么取值 T1[K] 就不会报错了
EmptyObject
type EmptyObject = {
    [K in any]: never
    // [K in string | number | symbol] 与下面等价 === PropertyKey
    // [K in PropertyKey] : never
    // 看了看大佬的   [K in PropertyKey]: never
}
// 测试用例
const shouldPass: EmptyObject = {
}; // 可以正常赋值
const shouldFail: EmptyObject = { // 将出现编译错误
    //   prop: "TS"  // 报错
}
StrictType
type Strict<T,U extends T> = {
    [P in keyof U] : P extends keyof T ? U[P] : never
}
// 更改以下函数的类型定义,让它的参数只允许严格SomeType类型的值
 function takeSomeTypeOnly<T extends SomeType>(x: Strict<SomeType,T>) { return x }
// 测试用例:
const x = { prop: 'a' };
takeSomeTypeOnly(x) // 可以正常调用
const y = { prop: 'a', addditionalProp: 'x' };
takeSomeTypeOnly(y) // 将出现编译错误
扩展一下:这是xy都符合的
// 这个是符合y的
type Stricts<T, U extends T> = {
    [P in keyof U] : P extends keyof T ? never : U[P]
}
function takeSomeTypeOnly<SomeType,T extends SomeType>(x: Stricts<SomeType,T>) { return x }
                                    
                                    
                                    
                                
宝哥,第二个问题的Exclusive类型,可不可以写成这样:
type Exclusive<T, U> = { [K in keyof T as K extends keyof U ? K : never]: T[K] }
type someType = {
hi: string,
hh: number
}
function takeSomeTypeOnly<T extends someType>(x: onlyType<T, someType>) {return x}
EmptyObject
type EmptyObject = Record<string, never>;
// 测试用例
const shouldPass: EmptyObject = {}; // 可以正常赋值
const shouldFail: EmptyObject = {
  // 将出现编译错误
  prop: 'TS',
};
                                    
                                    
                                    
                                
// 7.1
type EmptyObject = {
	[k in any]:never
} 
// 测试用例
const shouldPass: EmptyObject = {}; // 可以正常赋值
// const shouldFail: EmptyObject = { // 编译错误
//   prop: "TS"
// }
// 7.2
type SomeType =  {
  prop: string,
}
type onlyType<T1 extends T2, T2> = {
    [P in keyof T1]: P extends keyof T2 ? T1[P] : never
}
// 更改以下函数的类型定义,让它的参数只允许严格SomeType类型的值
function takeSomeTypeOnly<T extends SomeType>(x: onlyType<T, SomeType>) { return x }
// 测试用例:
const x = { prop: '2' };
console.log(takeSomeTypeOnly(x)) // 可以正常调用
// const y = { prop: 'a', addditionalProp: 'x' };
// takeSomeTypeOnly(y) // 将出现编译错误