Tìm kiếm trang web

Hàm dựng mới trả về một hàm khác trong TypeScript


Tôi có hàm này trong JavaScript:

function test()
{
  this.list = {};
  return (id) =>
  {
    if (!(id in this.list))
      this.list[id] = {default: 123};

    return this.list[id]
  }
}

const blah = new test();
blah("ok").mykey = "ok";
console.log(blah("ok").mykey);
console.log(blah("ok"));

Và tôi đang cố gắng chuyển nó sang định dạng TypeScript. Tôi hiểu rằng tôi sẽ phải sử dụng class, tuy nhiên làm thế nào để tôi trả về một hàm từ constructor của class?

Tôi không muốn có một thuộc tính bổ sung, myfunc, như một hàm new test().myfunc("ok"):

interface simpleObject
{
  [key:string]: string|number|object;
}

class Test
{
  private list:simpleObject;

  public myfunc(id:string)
  {
    if (!(id in this.list))
      this.list[id] = {default: 123};

    return this.list[id] as simpleObject;
  }

  constructor()
  {
    this.list = {};
  }

}

const blah = new Test();
blah.myfunc("test").mykey = "ok";
console.log(blah.myfunc("test").mykey);
console.log(blah.myfunc("test"))

Trên TS Playground

Câu trả lời #1

Tại sao bạn lại muốn sử dụng new trên thứ gì đó trả về một hàm? Chỉ cần gọi hàm đó mà không cần new.

Bạn có thể đạt được điều đó bằng cách giữ trạng thái của bạn trong các closure thay vì sử dụng this;

function test() {
  const list: {[id: string]: any} = {};
  return (id: string) =>  {
    if (!(id in list)) {
      list[id] = {default: 123};
    }
    return list[id]
  }
}

const blah = test();

Xem ví dụ trực tiếp

Tôi nghĩ đây là thứ bạn nên sử dụng. Nói như vậy, khả năng chỉ định những gì một constructor trả về hiện chưa có nhưng có thể sẽ có trong tương lai.

Tôi có thể đề xuất một giải pháp tạm thời (từ vấn đề được liên kết ở trên) hoặc câu trả lời này nhưng tôi không thấy lý do tại sao bạn lại muốn sử dụng điều đó cho trường hợp của mình vì những gì tôi đề xuất thì đơn giản hơn và không cần lớp ở đây.

Câu trả lời số 2

Hàm khởi tạo của một lớp sẽ trả về thể hiện của lớp đó, và đó là hành vi dự định. Trường hợp sử dụng của bạn thực sự không cần thiết phải dùng một lớp. Bạn vẫn có thể giữ hàm của mình và sử dụng this bên trong. Để nói với TypeScript loại của this là gì, bạn có thể sử dụng một tham số được bảo lưu:

type ReturnedFunction = (id: string) => string | number | object;
type TestFunction = () => ReturnedFunction;

function test(this: TestFunction): ReturnedFunction {
  // same code as before
}