Col | ColWithMain
работает взаимоисключающе. Вы определяете тип но полю type
. Почитайте https://habr.com/ru/articles/778060/. type Branch<T> = {
data: T;
children: Branch<T>[];
};
type Tree<T> = Branch<T>[];
const createTree = <T, K>(
collection: T[],
extractId: (entry: T) => K,
extractParentId: (entry: T) => K | null
): Tree<T> => {
const cache = new Map<K, Branch<T>>();
const tree: Tree<T> = [];
for (const entry of collection) {
const id = extractId(entry);
const parentId = extractParentId(entry);
const branch: Branch<T> = {
data: entry,
children: []
};
const root =
parentId !== null ? cache.get(parentId)?.children ?? tree : tree;
root.push(branch);
cache.set(id, branch);
}
return tree;
};
const tree = createTree(
item_list,
(entry) => entry.id,
(entry) => entry.parentId
);
- function Favorites(cardsFavorites: CardsProps): JSX.Element {
+ function Favorites({ cardsFavorites }: CardsProps): JSX.Element {
type FunctionDinamicParams = <T extends keyof TMap>(eventName: T, params: TMap[T]) => Promise<void>;
interface ComponentProps<V, D> {
value: V;
data: D;
}
const Component = <V, D>({ value, data }: ComponentProps<V, D>) => <></>;
type TResult = {
foo: boolean;
bar: string;
qux: number;
}
type TUnion = keyof TResult;
function fn<T extends TUnion>(value: T): TResult[T] {
switch (value) {
case 'bar': return '' as TResult[T];
case 'foo': return true as TResult[T];
case 'qux': return 1 as TResult[T];
default: throw new Error('Invalid value');
}
}
let a = fn('bar');
if
.function dispatch<T>(key: DispatchKey<T>, value: DispatchValue<T>): void;
function dispatch<T>(keys: DispatchKey<T>[], iterator: (key: DispatchKey<T>) => DispatchValue<T>): void;
function dispatch<T>(
keyOrKeys: DispatchKey<T> | DispatchKey<T>[],
valueOrIterator: DispatchValue<T> | ((key: DispatchKey<T>) => DispatchValue<T>)
): void {
if (Array.isArray(keyOrKeys) && typeof valueOrIterator === 'function') {
setState((prev) => {
const updated = keyOrKeys.map((key) => valueOrIterator(key));
console.log(updated);
return prev;
});
} else {
setState((prev) => ({
...prev,
[keyOrKeys]: valueOrIterator,
}));
}
}
<Routes>
<Route path="/" element={<Coins coins={coins} />} />
<Route path="/coin">
<Route index element={<Coin />} />
<Route path=":coinId" element={<Coin />} />
</Route>
</Routes>
type FilterOptions<T> = {
[K in keyof T]?: T[K] extends object ? FilterOptions<T[K]> : T[K];
};
const isOverlaps = <T>(entry: T, options: FilterOptions<T>): boolean => {
const keys = Object.keys(options) as Array<keyof T>;
return keys.every((key) => {
if (typeof options[key] === 'object') {
return isOverlaps(entry[key], options[key]!);
}
return entry[key] === options[key];
});
};
const filterBy = <T>(collection: T[], options: FilterOptions<T>) => {
return collection.filter((entry) => isOverlaps(entry, options));
};
MovieInfo[]
(все равно что Arrray<MovieInfo>
), а получаете один объект.React.useState<MovieInfo | null>(null);
<h1>{currentMovieDetail?.id}</h1>
interface IMain {
user: string;
val1: number;
val2: number;
val3: number;
}
type IShort = Partial<Omit<IMain, 'user'>>;
function sum(a: IMain, b: IShort) {
const keys = Object.keys(b) as (keyof IShort)[];
for (const key of keys) {
b[key] = a[key] - (b[key] ?? 0);
}
return b;
}
useState<T | null>(null)
, т.к. в таком случае можно легко проверить значение в условном рендеринге. А если Вы объявите в вашем компоненте нечто вроде React.FC<{ data: T }>
, то Object
(точнее ничего, кроме T
честным путём) не сможете внутрь прокинуть.interface IWrapper<T> {
component: T;
}
const Wrapper = <T extends React.ComponentType<any>>({
component: Component,
...props
}: React.PropsWithChildren<IWrapper<T> & React.ComponentProps<T>>) => <Component {...props} />;
interface IDefaultItemsLayout<T> {
items: T[];
}
export default function DefaultItemsLayout<T>(
props: React.PropsWithChildren<IDefaultItemsLayout<T>>
) { ... }