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



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

意义:

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

其中buildFromJsonfunction(input: Object): T

是否可以为 T 定义约束以仅接受定义了此静态成员的类型?

基于: 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}});

我认为这可能会回答你的问题。 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);

打字稿游乐场

最新更新