awesome-typescript icon indicating copy to clipboard operation
awesome-typescript copied to clipboard

「重学TS 2.0 」TS 练习题第七题

Open semlinker opened this issue 4 years ago • 11 comments

第七题

使用类型别名定义一个 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) // 将出现编译错误

请在下面评论你的答案

semlinker avatar Sep 14 '21 15:09 semlinker

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) // 将出现编译错误

semlinker avatar Sep 16 '21 01:09 semlinker

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) // 将出现编译错误

Mrlgm avatar Sep 25 '21 14:09 Mrlgm

// 使用类型别名定义一个 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 的严格匹配。

zhaoxiongfei avatar Oct 01 '21 14:10 zhaoxiongfei

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); // 将出现编译错误

yanglinxiao avatar Nov 19 '21 03:11 yanglinxiao

type EmptyObject = { [K in keyof any]: never }

// 测试用例 const shouldPass: EmptyObject = {}; // 可以正常赋值 const shouldFail: EmptyObject = { // 将出现编译错误 prop: "TS" }

waleiwalei avatar Mar 11 '22 07:03 waleiwalei

// 只支持特定属性-必须完全匹配

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) // 将出现编译错误

waleiwalei avatar Mar 11 '22 07:03 waleiwalei

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] 就不会报错了

Jarryxin avatar May 25 '22 04:05 Jarryxin

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 }

YJCCreateAHistory avatar May 25 '22 11:05 YJCCreateAHistory

宝哥,第二个问题的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}

glows777 avatar Aug 16 '22 08:08 glows777

EmptyObject

type EmptyObject = Record<string, never>;

// 测试用例
const shouldPass: EmptyObject = {}; // 可以正常赋值
const shouldFail: EmptyObject = {
  // 将出现编译错误
  prop: 'TS',
};

fishcoderman avatar Aug 25 '22 11:08 fishcoderman

// 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) // 将出现编译错误

shiyicyh avatar Aug 21 '23 04:08 shiyicyh