типизация через Record не совместима с конкретным ключом?
как решить данную ситуацию? Хочется получить интерфейс в котором есть одни единственный ключь типо number, и много других типо boolean как вариант;
Property 'some' of type 'number' is not assignable to 'string' index type 'boolean'
type TType = Record<string, boolean>;
interface IProps extends TType {
some?: number;
}
вариант с type TType = Record<string, boolean | number>; не подходит так как единственный тип с number это ключь some
Ответы (2 шт):
Да, проблема в том, что типизация через Record<string, boolean> не совместима с конкретным ключом some.
Одно из возможных решений - использовать объединение типов с помощью "|". Таким образом, можно задать тип IProps следующим образом:
type TType = Record<string, boolean>;
interface IProps extends TType {
some?: number;
[key: string]: boolean | number | undefined;
}
Теперь IProps содержит ключ some с типом number, а также другие ключи с типом boolean или number, которые могут быть добавлены в объект.
Такой интерфейс позволяет создать объект со свойством some типа number и другими свойствами типа boolean:
const props: IProps = {
some: 42,
flag1: true,
flag2: false,
flag3: undefined,
};
Желаемый тип можно объявить так:
type IProps = {
some?: number
} & {
[key in string]?: key extends "some" ? number : boolean
}
После этого переменные такого типа можно полноценно использовать.
Но есть проблема: присвоить переменной этого типа литеральный объект с полем some, отличным от undefined, тайпскрипт без явного приведения не позволит. А вот поменять значение поля уже существующей переменной можно без проблем.
Однако, по названию у меня сложилось впечатление, что речь о реакт-компонентах, а там можно нахимичить с дженериками: песочница
import React from 'react';
type Props<K extends string> = {
some?: number
} & {
[key in Exclude<K, "some">]: boolean
}
function Smth<T>(props: T & Props<string & keyof T>) {
return null
}
function App() {
return (
<>
<Smth />
<Smth some={42} />
<Smth qqq={true} />
<Smth some={42} qqq={true} />
</>
)
}