Ошибка с типом "никогда" при использовании 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 ничего не добавляется.