如何自动将参数应用于类构造函数?

时间:2018-12-28 10:06:46

标签: javascript typescript ecmascript-6

我有一个es6类User和下面给出的全局函数map()

class  User {
  constructor(public name: string) {}
}

const map = <T, R>(project: (value: T) => R) => {}

代替编写以下内容:

map((value) => new User(value))

我想(以某种方式)写一些东西:

map(new User)

我不确定这是否可行。

6 个答案:

答案 0 :(得分:6)

您可以在您的类中创建一个静态函数,该函数采用值param并返回一个新的User:

class User {
  static createUser(value) {
    return new User(value)
  }
}

然后使用:

map(User.createUser)

答案 1 :(得分:5)

您不能直接这样做。如果您控制目标函数(即不是股票 // Get system properties int count = 5; while (count > 0) { try { Properties properties = System.getProperties(); properties.put("mail.pop3.port", "110"); properties.put("mail.pop3.host", "example.outlook.com"); // properties.put(String.format("mail.%s.port", "pop3"), port); properties.setProperty( String.format("mail.%s.socketFactory.fallback", "pop3"), "false"); Session session = Session.getDefaultInstance(properties,null); Store store = session.getStore("pop3"); store.connect("example.outlook.com, username, password); System.out.println(store); if (getInboxFolder() != null) { Message[] msgs = inbox.getMessages(); for (Message msg : msgs) { if (msg.getSubject().contains("Test")) { Multipart mp = (Multipart) msg.getContent(); BodyPart bp = mp.getBodyPart(0); bp.getContent(); MimeMultipart mimeMultipart = (MimeMultipart) msg.getContent(); String bodyContent = getTextFromMimeMultipart(mimeMultipart); return bodyContent; } } return null; } count--; } catch (Exception e) { count--; } } return null; } 函数),则可以使用构造函数代替函数:

map

另一个更灵活的解决方案是使用辅助函数,该函数将构造函数转换为所需的函数,尽管它比原始版本短很多:

class User { constructor(private id: number) { }}
function map<TIn, T>(value: TIn, ctor: new (a: TIn) => T): T{
    return new ctor(value)
}
map(10, User)

答案 2 :(得分:2)

如果未使用new调用该函数,则可以使用new.target添加一个检查,然后使用new调用然后调用该函数。

function Person(name) {
    if (!new.target) return new Person(...arguments);
    this.name = name;
}

var names = ['Jane', 'Dan', 'Grace', 'Paul'],
    instances = names.map(Person);

console.log(instances);

答案 3 :(得分:2)

您所描述的模式称为范围安全的构造器。可以通过重载构造函数来实现它,从而使其与一起使用,而无需使用new关键字。

interface User {
  name: string;
}

interface UserConstructor {
  new (name: string): User;
  (name: string): User;
}

相同的技巧用于ArrayDate之类的全局对象。

我们需要识别是否使用了new关键字:

const User = function (this: User | void, name: string): User {
  if (!(this instanceof User)) {
    return new User(name);
  }

  this.name = name;
  return this;
} as UserConstructor;

您的课程刚变得new无关。

console.log(
  new User('Bob'),
  User('Alice'),
);

这使我们能够编写:

['Alice', 'Bob'].map(User); // $ExpectType User[]

答案 4 :(得分:2)

这是JS的oop vs fp辩论中的一个众所周知的“问题”-类构造函数与函数构造函数

由于es6类需要 new运算符,因此无法编写类似map(new User)

的内容

您需要一个围绕类构造函数的包装,该包装通过函数调用创建实例。 IMO,@baboo's approach是未来之路

class MyClass {
  // ...

  static create(...args) {
    return new MyClass(...args)
  }
}
const a = new MyClass('hello', [])
const b = MyClass.create('world', 123])

您可以详细了解new here的问题。

还要结帐daggy - Library for creating tagged constructors

答案 5 :(得分:1)

如果您想要通用的解决方案,并且不能修改类,则可以使用高阶函数:

function make(klass) {
    return (...params) => new klass(...params);
}

// this:
map((value) => new User(value));

// becomes this:
map(make(User));