简体   繁体   English

如何在 typescript 中的 object 文字中键入带有“this”的方法?

[英]How can I type a method with 'this' inside object literal in typescript?

const log = {
  counter: {
    a: 1,
    b: 2,
    c: 3,
  },
  increment(entry: keyof typeof this.counter){
    this.counter[entry]++;
  }
};

function incrementLog(entry:keyof typeof log.counter){
    log.counter[entry]++;
}

incrementLog('a'); // ok
incrementLog('d'); // error, must be 'a' | 'b' | 'c'
log.increment('a'); // ok
log.increment('d'); // no error

Playground Link 游乐场链接

I want to enforce the argument type of increment method to be keyof typeof log.counter , which is 'a' | 'b' | 'c'我想强制increment方法的参数类型为keyof typeof log.counter ,即'a' | 'b' | 'c' 'a' | 'b' | 'c' 'a' | 'b' | 'c' . 'a' | 'b' | 'c' I can achieve it in the standalone function, but it doesn't work in the increment method: 'this' is not defined.我可以在独立的 function 中实现它,但它在increment方法中不起作用: 'this' is not defined.

I've also tried log.counter instead of this.counter on the method definition, but that creates a 'circular initializer' which also doesn't work as intended.我还在方法定义上尝试log.counter而不是this.counter ,但这会创建一个“循环初始化程序”,它也不能按预期工作。

I hope not to manually type the log or manually type the counter , because when I make changes to the object, I hope to only make changes in one place.我希望不要手动输入log或手动输入counter ,因为当我对 object 进行更改时,我希望只在一个地方进行更改。

When writing object-oriented code in TypeScript, it's a lot easier to use class syntax than it is to force things to work with plain object literals:在 TypeScript 中编写面向对象的代码时,使用 class 语法比强制使用普通的 object 文字要容易得多:

class Log {
  counter = {
    a: 1,
    b: 2,
    c: 3
  };

  increment(entry: keyof Log['counter']) {
    this.counter[entry]++;
  }
}

const log = new Log();

function incrementLog(entry:keyof Log['counter']) {
  log.counter[entry]++;
}

incrementLog('a'); // ok
incrementLog('d'); // error
log.increment('a'); // ok
log.increment('d'); // error

Define counter before log .log之前定义counter You cannot reference type in the middle of expression which defines the type.您不能在定义类型的表达式中间引用类型。 You can easily avoid duplicating definition/initialization.您可以轻松避免重复定义/初始化。

const counter = {
    a: 1,
    b: 2,
    c: 3,
};
const log = {
  counter,
  increment(entry: keyof typeof counter){
    this.counter[entry]++;
  }
};

function incrementLog(entry:keyof typeof log.counter){
    log.counter[entry]++;
}

incrementLog('a'); // ok
incrementLog('d'); // error, must be 'a' | 'b' | 'c'
log.increment('a'); // ok
log.increment('d'); // error, must be 'a' | 'b' | 'c'

You should create a type or interface for log :您应该为log创建一个类型或接口:

interface Log<T extends {[key: string]: number}> {
    counter: T;
    increment(element: keyof T): void;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM