Typescript: применять внутренний тип, но возвращать фактический тип - PullRequest
1 голос
/ 13 марта 2019

У меня есть следующий код:

class ValueGetter {
  getValues() {
    return {
      value1: this.getValueAsBoolean(somewhere.something),
      value2: this.getValueAsBoolean(somewhere.somethingElse)
    }
  }
}

Typescript знает точный тип возврата функции, а именно.

{
  value1: boolean,
  value2: boolean
}

Что действительно удобно, что я могу даже сделатьгде-то еще:

class MyFoo {
  myBar: ReturnType<ValueGetter['getValues']>
}

Теперь я хочу принудительно установить getValues, чтобы он мог возвращать только следующий тип {[key: string]: boolean}

Но если я добавлю это как тип возвратаиз getValues(), я теряю точный тип возвращаемого значения с именованными ключами, который выведен для меня Typescript.

Есть ли способ применить эту типизацию только для «изнутри» getValues, не теряя при этом крутости?Волшебство дедукции с «именованными ключами» - может повторить Typescript?

Ответы [ 2 ]

2 голосов
/ 13 марта 2019

Несмотря на то, что на этот вопрос ответили, вот лучший способ сделать то, что вы хотите, без добавления каких-либо накладных расходов времени выполнения:

type HasType<T extends C, C> = T;
function getValues() {
    let foo = {
        value1: Boolean(100),
        value2: 123
    };
    return <HasType<typeof foo, Record<string, boolean>>>foo;
    //              ^^^^^^^^^^ error here
}

Вот демо

(такжепометьте это как принятое, если вы считаете, что это лучше)

1 голос
/ 13 марта 2019

Это общая проблема, связанная с желанием обеспечить, чтобы значение удовлетворяло определенному ограничению, но в то же время сохраняло фактический тип значения.

К сожалению, машинопись не поддерживает какой-либо специальный синтаксис для этого. Лучшее, что вы можете сделать - это иметь функцию с параметром типа с ограничением. Тип будет выведен из фактического переданного значения, но он будет проверен на соответствие ограничению:

class ValueGetter {
    getValues() {
        return constrainToBooleanValues({
            value1: true,
            value2: false,
            worngValue: 1// err
        })
    }
}

function constrainToBooleanValues<T extends Record<string, boolean>>(o: T) {
    return o;
}

Вы можете даже обобщить функцию:

class ValueGetter {
    getValues() {
        return constrain<Record<string, boolean>>()({
            value1: true,
            value2: false,
            worngValue: 1// err
        })
    }
}

function constrain<C>() {
    return <T extends Record<string, boolean>>(o: T) => o;
}
...