Ошибка с типом "никогда" при использовании extends keyof в качестве универсального типа

Мой код в машинописи:

class Author {
  id: number;
}
type Getter<S, A> = (obj: S) => A;

function propGetter<S, K extends keyof S>(prop: K): Getter<S, S[K]> {
  return o => o[prop];
}
const _id: Getter<Author, number> = propGetter('id');

Я получил ошибку:

Argument of type '"id"' is not assignable to parameter of type 'never'.

Код на машинописной площадке

Насколько я понимаю, тип K должен быть строками ключей типа S. Как это унифицировано, чтобы никогда? Это потому, что в качестве универсального параметра используется сопоставленный тип?

1 ответ

Компилятор не может определить тип S когда вы только проходите K,
Это будет работать, если вы сделаете это:

const _id: Getter<Author, number> = propGetter<Author, "id">('id');

Или если вы измените функцию, чтобы получить экземпляр S (и тогда он выведет тип):

function propGetter<S, K extends keyof S>(obj: S, prop: K): Getter<S, S[K]> {
    return o => o[prop];
}
const _id: Getter<Author, number> = propGetter(new Author(), 'id');

редактировать

После второй мысли вы можете сделать это:

function propGetter<S>(prop: keyof S): Getter<S, S[typeof prop]> {
    return o => o[prop];
}
const _id = propGetter<Author>('id'); // type of _id is Getter<Author, number>

2-е редактирование

Мне не нравится добавлять код, который бесполезен в скомпилированном js, просто чтобы сделать компилятор счастливым.
Это такой случай, я думаю, что лучшим решением для этого является что-то вроде этого:

function propGetter<S>(prop: keyof S): Getter<S, any> {
    return o => o[prop];
}

const _id = propGetter<Author>('id') as Getter<Author, number>;
// or
const _id: Getter<Author, number> = propGetter<Author>('id');

Таким образом, вы получаете безопасность типов, менее многословно, и к js ничего не добавляется.

Другие вопросы по тегам