TS (2352) Объявить объект с динамическими свойствами и одно свойство с определенным типом - PullRequest
0 голосов
/ 28 мая 2019

Мне нужно создать объект, который будет содержать одно свойство с именем 'state', которое будет иметь универсальный тип, а все остальные свойства будут функциями с переопределенным контекстом.Я не уверен, что это возможно, из-за этого я решил написать здесь.

У меня есть код:

declare interface ContextModule<State> {
  state: State
}

export declare interface SuperModule<State = any> {
  state?: State | any,
  [methodName: string]: (this: ContextModule<State>, ...args: any[]) => any
}

const lol = {
  getFoo (): any {
    return this.state.foo
  }
} as SuperModule

В этом коде у меня нет ошибок,Он выполняется успешно, но если я добавлю

declare interface ContextModule<State> {
  state: State
}

export declare interface SuperModule<State = any> {
  state?: State | any,
  [methodName: string]: (this: ContextModule<State>, ...args: any[]) => any
}

const lol = {
  getFoo (): any {
    return this.state.foo
  },
+  state: {       // added this property
+    foo: 'string'
+  }
} as SuperModule

, тогда я увижу вывод

Conversion of type '{ getFoo(this: ContextModule<any>): any; state: { foo: string; }; }' to type 'SuperModule<any>' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
  Property 'state' is incompatible with index signature.
    Type '{ foo: string; }' is not comparable to type '(this: ContextModule<any>, ...args: any[]) => any'.
      Type '{ foo: string; }' provides no match for the signature '(this: ContextModule<any>, ...args: any[]): any'.ts(2352)

Я понимаю, что проблема связана с тем, что TypeScript пытается привести свойство state к [methodName: string]: (this: ContextModule<State>, ...args: any[]) => any, но почему, если я объявил это свойство до объявления динамических свойств

Может быть, кто-то видел ту же проблему.Надеюсь на вашу помощь, спасибо!

1 Ответ

1 голос
/ 29 мая 2019

Единственный способ заставить эту работу работать чисто, это использовать тип пересечения, но кажется, что пересечение динамических типов и типов с фиксированными свойствами (от типа, отличного от динамического реквизита) может быть создано только с использованием Object.assign .

Вот мой упрощенный пример того, как это может работать:

interface MyType {
    requiredProp1: string
}
interface MyOtherType{
    [key: string]: number
}
type ISect = MyType & MyOtherType

const obj: ISect = Object.assign({ requiredProp1: "ff" }, { foo: 1 })

const rp1 = obj.requiredProp1 //string
const foo = obj.foo //number
...