打字稿功能属性

时间:2019-08-29 08:37:25

标签: typescript

首要:答案很可能就在那里,但是我不知道它的名字,所以我很遗憾找不到它。

那没关系;我的问题是我想在打字稿中编辑函数的属性(声明它们是因为未声明它们,所以对其进行了声明),但不知道该怎么做。

您只需使用JavaScript即可:

console.log('logError00 ==============================');
logError00('Foo');
logError00('Bar');
logError00('hey');

function logError00(error) {
    const _this = logError00;
    if(_this.counter === undefined) _this.counter = 1;
    else _this.counter++;
    console.log(`${_this.counter} | ${error}`);
}

或(这可能不明智,因为它需要在函数调用之前声明):

logError01.counter = 0;
function logError01(error) {
    const _this = logError01;
    _this.counter++;
    console.log(`${_this.counter} | ${error}`);
}

console.log('logError01 ==============================');
logError01('Foo');
logError01('Bar');
logError01('hey');

最后,我想做的是创建一个Class,该类跟踪方法调用的平均次数,而无需声明变量,例如:

class MyClass {
    private func1Count = 0;
    private func2Count = 0;
    [...]
}

这就是我在JS中工作的方式:

class MyError {
	constructor(message) {
		this.log.counter = 0;
		this.message = message;
	}

	log() {
		this.log.counter++;
		console.log(`${this.log.counter} | ${this.message}`);
	}
}



console.log('MyError (class) ==============================');
const myError = new MyError('Some Message');
myError.log();
myError.log();
myError.log();

这就是我要阻止的内容,但是可以正常编译:

wouldBeMeh('Foo');
wouldBeMeh('Bar');
wouldBeMeh('Hey!');

function wouldBeMeh(error: string) {
    const _this = (wouldBeMeh as any);

    if(_this.counter === undefined) _this.counter = 1;
    else _this.counter++;

    console.log(`${_this.counter} | ${error}`);
}

谢谢。

2 个答案:

答案 0 :(得分:1)

对于某项功能,它仅适用。使用Typescript,您可以将成员添加到当前作用域中的函数中:



wouldBeMeh.counter = 0;
function wouldBeMeh(error: string) {


    if(wouldBeMeh.counter === undefined) wouldBeMeh.counter = 1;
    else wouldBeMeh.counter++;

    console.log(`${wouldBeMeh.counter} | ${error}`);
}


wouldBeMeh('Foo');
wouldBeMeh('Bar');
wouldBeMeh('Hey!');

Play

答案 1 :(得分:1)

您说您不想声明诸如func1Count之类的成员变量,但这确实是某人执行此类操作的最直接方法,特别是因为它使用TypeScript编译器的属性和方法了解。如果您可以解释为什么,您不想使用成员变量,则可能有人可以提出一种满足您需要的实现,而不必花太多的时间。

现在,我假设您确实需要向方法中添加属性(而不是独立函数,在TS3.1中添加了support for which)。 TypeScript通常不允许expando属性;如果要向某事物添加属性,则需要知道其类型以具有该属性。

对于无法通过对象文字创建的类似函数的操作,最简单的方法是使用Object.assign()。形式的东西

const funcWithProp = Object.assign(function(){}, {prop: ""});

将被推断为具有类型

// const funcWithProp: (() => void) & { prop: string; }

既可以用作函数,也可以用作prop键控对象:

funcWithProp(); // okay
funcWithProp.prop = "hey" // okay

所以,让我们看一下您的课程,看看该怎么做:


我不确定您是否想拥有一个计数器,该计数器在MyError任何实例调用其log()方法时是否递增,或者是否需要单独的计数器? MyError的每个实例的计数器。所以我会同时实现。

如果您想要一个计数器,则应这样操作:

class MyError {
  message: string;
  constructor(message: string) {
    this.message = message;
  }
}
interface MyError {
  log: ((this: MyError) => void) & { counter: number };
}
MyError.prototype.log = Object.assign(
  function(this: MyError) {
    this.log.counter++;
    console.log(`${this.log.counter} | ${this.message}`);
  },
  { counter: 0 }
);

请注意,我必须使用declaration merging并直接在log上设置MyError.prototype。方法通常以原型出现(每个类只有一个),并且当您在class中声明一个方法时,无法注释您希望它具有更多的属性。因此,正确的注释需要放入interface MyError内,该注释将合并到class中,并且实际的实现将分配给MyError.prototype.log并使用Object.assign()。还要注意,log函数签名具有this parameter。那只是类型系统的一部分,它使编译器知道您只能在MyError类型的对象上作为方法调用该函数,并且该函数的实现可以访问{{1} }作为this的实例。

让我们看看它是否有效:

MyError

看起来不错。


如果您希望每个const myError = new MyError("Some Message"); myError.log(); // 1 | Some Message const myError2 = new MyError("Other Message"); myError.log(); // 2 | Some Message myError2.log(); // 3 | Other Message myError.log(); // 4 | Some Message 实例都有自己的日志计数器,该怎么办?我们可以这样:

MyError

现在,我们不能使用原型上使用的常规方法,否则整个class MyError { message: string; constructor(message: string) { this.message = message; } log = Object.assign( function(this: MyError) { this.log.counter++; console.log(`${this.log.counter} | ${this.message}`); }, { counter: 0 } ); } 类中只有一个。您想跟踪每个实例对MyError的调用,这意味着每个实例需要单独的log()属性。但是,只有在每个实例都有单独的counter实现时,您才能这样做(好吧,除非您使用log()成员变量,但您不想这样做)。因此,我们不是将MyError用作方法,而是使它成为函数值实例属性,并使用log进行了初始化。我们使用与之前相同的=代码,并且可以正常工作。

好吧,让我们看看它是否有效:

Object.assign(...)

看起来不错。


好的,希望能有所帮助;祝你好运!

Link to code