静态方法包含的定义类型参数约束

问题描述 投票:0回答:2

在使用序列化程序的情况下,我可以定义类型参数约束,使其类型具有特定的静态成员/“静态”实现接口吗?

含义:

function getStuff<T>(...) -> T {
  T.buildFormJson(getStuffJson(...))
}

其中buildFromJsonfunction(input: Object): T

我可以为T定义一个约束,使其只接受定义了此静态成员的类型吗?

typescript generic-programming
2个回答
0
投票

基于:https://github.com/microsoft/TypeScript/issues/13462#issuecomment-275860898

interface JsonDeserializable<T> {
  fromJson(obj: Object): T;
}
interface JsonSerializable {
  toJson(): Object;
}

用法:

import * as assert from "assert";

class Point2D {
  x: number;
  y: number;

  constructor(x: number, y: number) {
    this.x = x;
    this.y = y;
  }


  toJson(): Object {
    return this;
  }

  static fromJson(obj: Object): Point3D {
    return new Point3D(obj['x'], obj['y'], obj['z']);
  }
}

class Point3D {
  x: number;
  y: number;
  z: number;

  constructor(x: number, y: number, z: number) {
    this.x = x;
    this.y = y;
    this.z = z;
  }

  toJson(): Object {
    return this;
  }

  static fromJson(obj: Object): Point3D {
    return new Point3D(obj['x'], obj['y'], obj['z']);
  }
}


class Baz {
  foo: Point2D;
  bar: Point3D;

  constructor(foo: Point2D, bar: Point3D) {
    this.foo = foo;
    this.bar = bar;
  }

  toJson(): Object {
    return {
      foo: this.foo.toJson(),
      bar: this.bar.toJson()
    }
  }

  static fromJson(obj: Object): Baz {
    return new Baz(Point2D.fromJson(obj['foo']), Point3D.fromJson(obj['bar']));
  }
}



var DATA: Object = {};

function getJson(): Object {
  return DATA;
}

function saveJson(o: Object) {
  DATA = o;
}


// Only accepts T that is serializable
function save<T extends JsonSerializable>(o: T) {
  const json = o.toJson();
  saveJson(json);
}

// Only accepts T that is deserializable
function load<InstanceType>(cls: JsonDeserializable<InstanceType>): InstanceType {
  const data = getJson();

  return cls.fromJson(data);
}

// Only accepts T that is both serializable and deserializable
function testSerde<T extends JsonSerializable>(cls: JsonDeserializable<T>, obj: Object) {
  const instance = cls.fromJson(obj);
  const json = instance.toJson();

  assert.deepEqual(json, obj);
}


const baz = new Baz(new Point2D(1,2), new Point3D(1,2,3));

save(baz);
console.log(load(Baz)); // Baz object
testSerde(Baz, { foo: { x: 1, y: 2 }, bar: {x: 1, y: 2, z: 3}});

0
投票

思考这可能会回答您的问题。 JavaScript中的class只是花哨的function,而类的static成员只是该函数的属性(即,它不是该函数的prototype的成员)。

因此,我们可以使T扩展为Function & { new(...args: any): any } & { buildFormJson(input: object): InstanceType<T> }。我已经将交集的前两个部分抽象为一个称为ClassType<S>的通用类型,其中S是定义静态成员的接口。

function getStuffJson() {
    return {};
}

type ClassType<S> = Function & { new(...args: any): any } & S;

function getStuff<T extends ClassType<{ buildFormJson(input: object): InstanceType<T> }>>(myClass: T) {
    return myClass.buildFormJson(getStuffJson());
}

class TestClass {
    static buildFormJson(): TestClass {
        return {};
    }
}

getStuff(TestClass);

TypeScript Playground

© www.soinside.com 2019 - 2024. All rights reserved.