#typescript
#typescript
Вопрос:
Пример ограничения выбора свойства только свойствами универсального параметра T
:
type Person = {
name: string;
age: number;
locations: number[];
}
function getProperty<T, K extends keyof T>(obj: T, key: K) {
return obj[key];
}
const p1: Person = { name : "Foo", age: 55, locations: [1,2,3,4] };
const name = getProperty(p1, "locations"); // Output: [1,2,3,4]
Чего я хочу добиться сейчас, так это ограничить K
выбор ключа объекта не только keyof T
определенным типом, но и K
определенным типом, например: Массив. Пример использования:
const name = getProperty<Array<number>>(p1, "name"); // Should fail as name is not Array<number>
const name = getProperty<Array<number>>(p1, "locations"); // Should succeed
Ответ №1:
Максимум, чего я могу достичь: игровая площадка
Используя эту статью для решения :
type SubType<Base, Condition> = Pick<Base, {
[Key in keyof Base]: Base[Key] extends Condition ? Key : never
}[keyof Base]>;
type Person = {
name: string;
age: number;
locations: number[];
}
function getProperty<T, U extends T[keyof T], K extends SubType<T, U> = SubType<T, U>>(obj: T, key: keyof K): U {
return obj[key as unknown as keyof T] as U;
}
type SubType<Base, Condition> = Pick<Base, {
[Key in keyof Base]: Base[Key] extends Condition ? Key : never
}[keyof Base]>;
// Examples --> Hover on D to see SubType result
// https://medium.com/dailyjs/typescript-create-a-condition-based-subset-types-9d902cea5b8c
type D = SubType<Person, number>;
// --------------------
const p1: Person = { name : 'Foo', age: 55, locations: [1,2,3,4] };
// Should fail as foo is not in Person
const var1 = getProperty(p1, 'foo');
// Should fail as name is not of type Array<number> in Person
const var2 = getProperty<Person, Array<number>>(p1, 'name');
// Should succeed as name is in Person
const var3 = getProperty(p1, 'name');
// Should succeed as locations is in Person and is a number[]
const var4 = getProperty<Person, number[]>(p1, 'locations');
// Should succeed as age is in Person and is a number
const var5 = getProperty<Person, number>(p1, 'age');
// Should fail as age is in Person and is not a string
const var6 = getProperty<Person, string>(p1, 'age');
console.log(var1);
console.log(var2);
console.log(var3);
console.log(var4);
console.log(var5);
console.log(var6);
Комментарии:
1. Ничего себе выдающийся пример. Я никогда не понимаю, где границы между ограничениями встроенного типа в области универсального параметра
<>
и отдельным типом. Я думаю, что после его разделения он становится намного чище для чтения. Большое спасибо!