useState<User[] | null>(null);
Здесь Вы пишите, что в стейте у Вас либо null либо массив юзеров.а здесь Вы уговорили TS что ответ - это 1 юзер и пытаетесь передать его в стейт.const _user = (await response.json()) as User; setItem(_user);
а вот здесь у Вас компонент так же принимает только одного юзера, но передаете Вы емуinterface IUserInfoProps { user: User; }
<UserInfo user={item} />
значение из стейта с типом User[] | null
string[] | Record<string, any>[]
- это или массив строк или массив объектов (ключ - любая строка, значение любого типа). Данный тип не позволит смешивать строки и объекты в одном массиве, либо то либо другое.(string | Record<string, any>)[]
(массив из строк или объектов в перемешку).type RulersMap<R extends Record<string, unknown>> = {
[K in keyof R]: R[K] extends number
? `${R[K]}px`
: R[K] extends Record<string, unknown>
? RulersMap<R[K]>
: R[K];
};
и привести результат к типу RulersMap<typeof rulers>
type SumOrConcat = {
(a: number, b: number): number
(a: string, b: number): string
}
const result: SumOrConcat = (a: number | string, b: number): any => {
if (typeof a === 'number') {
return a + b
}
return `${a} ${b}`
}
Но надежнее все же так:type SumOrConcat = {
(a: number, b: number): number
(a: string, b: number): string
}
const result = ((a: number | string, b: number): number | string => {
if (typeof a === 'number') {
return a + b
}
return `${a} ${b}`
}) as SumOrConcat;
Ну и надо отметить, что синтаксис самих перегрузок таких проблем не имеет, хотя стрелочную функцию с ним не опишешьfunction sumOrConcat(a: number, b: number): number;
function sumOrConcat(a: string, b: number): string;
function sumOrConcat(a: number | string, b: number): number | string {
if (typeof a === 'number') {
return a + b
}
return `${a} ${b}`
}
const result = sumOrConcat;
constructor
любого типа T
, который является подтипом типа { new (...args: any[]): {} }
{ new (...args: any[]): {} }
- это абсолютно тоже самое, что и new (...args: any[]) => {}
. Это сигнатура конструктора, с любым количеством любых элементов и инстанциирующий значение с типом {}
.{}
- это множество всех не нулевых значений (не только объектов), то есть по сути это как тип any, но без null | undefined
и с не сломанной вариантностью. Здесь его безболезненно можно заменить на тип unknown
, в отличии от тех же аргументов, где из-за контрвариантности аргументов функций (и конструкторов) предикаты на типах ломаются и без any нормально не сделать.styled.li<{ menu?: any }>`
``
) можно применить функцию-тэг, она будет вызвана с массивом фиксированных строк и интерполируемыми значениями (`${/* вот этими */ value}`
).{ menu?: any }
) или не передавать (тогда дженерик выведется автоматически из аргументов)А тут в качестве интерполируемого значения передается стрелочная функция, в которой деструктурирован первый аргумент. В данном случае это нормально, так как функция-тег получит данную функцию "как есть", без приведения к строке.${({ menu }) => menu && css
export class AlbumItemComponent implements OnInit {
//@Input() public album: any;
@Input() public album: Album[];
<div *ngFor="let album of albums">
<app-album-item [album]="album"></app-album-item>
</div>
const DEFAULT_KEY = 'defaultKey';
type DEFAULT_KEY = typeof DEFAULT_KEY;
type BaseObject = Record<PropertyKey, Record<PropertyKey, unknown>>;
type PropertyOfObject<T extends BaseObject> = {
<K extends keyof T>(key: K): DEFAULT_KEY extends keyof T[K] ? T[K][DEFAULT_KEY] : null;
<K0 extends keyof T, K1 extends keyof T[K0]>(key0: K0, key1: K1): T[K0][K1];
};
function getPropertyOfObject<T extends BaseObject>(obj: T): PropertyOfObject<T> {
type K0 = keyof T;
type K1 = DEFAULT_KEY | keyof T[K0];
return ((keyOne: K0, keyTwo: K1 = DEFAULT_KEY) =>
obj[keyOne]?.[keyTwo] ?? null
) as PropertyOfObject<T>;
}
function getProductCollection(func:
| ((error: Error, data: null, info: string) => any)
| ((error: null, data: ProductUnit[], info: string) => any)
): void {}
((error: Error, data: null, info: string) => any) | ((error: null, data: ProductUnit[], info: string) => any)
Это совершенно не тоже самое, что(error: null | Error, data: ProductUnit[] | null, info: string) => any
Ну и кстати, перегрузка в таком случае не особо нужна, и даже вредна.function getProductCollection(func: {
(error: Error, data: null, info: string): any;
(error: null, data: ProductUnit[], info: string): any;
}): void {}
Это защитит внутренности getProductCollection от его неправильного вызова, но снаружи, Вы получите в колбэк обобщенный тип:(error: null | Error, data: ProductUnit[] | null, info: string) => any
Это заставит вызывающий код делать или лишние проверки, или кастовать типы, так что если не нужны сильные гарантии в пределах одной функции, то можно обойтись простым вариантом:function getProductCollection(func: (error: null | Error, data: ProductUnit[] | null, info: string) => any): void { }
function loop(step: number) {
for (let i = 0; i < 100; i += step)
console.log(i);
}
В данном коде нет ошибки, ошибка в другом месте. Typescript вообще не меняет логику в выходном javacript. Я бы поискал другие места, где Вы вызываете эту функцию. Где-то Вы передаете в нее строку, убедив typescript через оператор as, что это число.type InferValueTypes<T> = T extends { [key: string]: infer IDontKnowWhat2CallThis } ? IDontKnowWhat2CallThis : never
type InferValueTypes<T extends Record<string, unknown>> = T[string];