Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

「重学TS 2.0 」TS 练习题第四十五题 #66

Open
semlinker opened this issue Oct 1, 2021 · 4 comments
Open

「重学TS 2.0 」TS 练习题第四十五题 #66

semlinker opened this issue Oct 1, 2021 · 4 comments

Comments

@semlinker
Copy link
Owner

实现 JsonifiedObject 工具类型,用于对 object 对象类型进行序列化操作。具体的使用示例如下所示:

type JsonifiedObject<T extends object> = // 你的实现代码

type MyObject = {
  str: "literalstring",
  fn: () => void,
  date: Date,
  customClass: MyClass,
  obj: {
    prop: "property",
    clz: MyClass,
    nested: { attr: Date }
  },
}

declare class MyClass {
  toJSON(): "MyClass";
}

/**
 * type JsonifiedMyObject = {
 *  str: "literalstring";
 *  fn: never;
 *  date: string;
 *  customClass: "MyClass";
 *  obj: JsonifiedObject<{
 *    prop: "property";
 *    clz: MyClass;
 *    nested: {
 *      attr: Date;
 *    };
 *   }>;
 * }
*/
type JsonifiedMyObject = Jsonified<MyObject>;
declare let ex: JsonifiedMyObject;
const z1: "MyClass" = ex.customClass;
const z2: string = ex.obj.nested.attr;

请在下面评论你的答案

@sunboyZgz
Copy link

sunboyZgz commented Oct 2, 2021

declare class MyClass {
  toJSON(): "MyClass";
}
type sss = never extends void ? true : false;
type Jsonified<T extends object> = {
  [K in keyof T]: T[K] extends { toJSON(): infer Return }
    ? ReturnType<T[K]["toJSON"]>
    : T[K] extends (...arg: any[]) => any
    ? never
    : T[K] extends object
    ? Jsonified<T[K]>
    : T[K];
};

type MyObject = {
  str: "literalstring";
  fn: () => void;
  date: Date;
  customClass: MyClass;
  obj: {
    prop: "property";
    clz: MyClass;
    nested: { attr: Date };
  };
};

/**
 * type JsonifiedMyObject = {
 *  str: "literalstring";
 *  fn: never;
 *  date: string;
 *  customClass: "MyClass";
 *  obj: JsonifiedObject<{
 *    prop: "property";
 *    clz: MyClass;
 *    nested: {
 *      attr: Date;
 *    };
 *   }>;
 * }
 */
type JsonifiedMyObject = Jsonified<MyObject>;
declare let ex: JsonifiedMyObject;
const z1: "MyClass" = ex.customClass;
const z2: string = ex.obj.nested.attr;

@zhaoxiongfei
Copy link

type Jsonified<T extends object> = {
  [k in keyof T]: T[k] extends object
    ? "toJSON" extends keyof T[k]
      ? T[k]["toJSON"] extends (...args: any[]) => infer R
        ? R
        : never
      : T[k] extends (...args: any[]) => any
        ? never
        : Jsonified<T[k]>
    : T[k];
};

type MyObject = {
  str: "literalstring";
  fn: () => void;
  date: Date;
  customClass: MyClass;
  obj: {
    prop: "property";
    clz: MyClass;
    nested: { attr: Date };
  };
}

declare class MyClass {
  toJSON(): "MyClass";
}

/**
 * type JsonifiedMyObject = {
 *  str: "literalstring";
 *  fn: never;
 *  date: string;
 *  customClass: "MyClass";
 *  obj: JsonifiedObject<{
 *    prop: "property";
 *    clz: MyClass;
 *    nested: {
 *      attr: Date;
 *    };
 *   }>;
 * }
*/
type JsonifiedMyObject = Jsonified<MyObject>;
declare let ex: JsonifiedMyObject;
const z1: "MyClass" = ex.customClass;
const z2: string = ex.obj.nested.attr;

思路: 比较费事儿一些,要枚举所有可能遇到的情况,测试用例对于function类型没有详细说明,我按照never统一输出的。如果需要考虑函数的返回值的话,多一层 extends 判断。

@jackwangwj
Copy link

type Jsonified = {
[K in keyof T]: changeType<T[K]>
}

type changeType = [T] extends [string]
? T
: T extends (...args: any) => infer R
? R & 1
: T extends Date
? string : T extends { toJSON(): infer C } ? C
: T extends object ? {
[K in keyof T]: T[K] extends { toJSON(): infer C } ? C : changeType<T[K]>
} : false

@zjxxxxxxxxx
Copy link

type Jsonified<T> = T extends Date
  ? string
  : T extends MyClass
  ? "MyClass"
  : T extends () => void
  ? never
  : T extends object
  ? {
      [K in keyof T]: Jsonified<T[K]>;
    }
  : T;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants