value
уже существует, а остальной мусор пофиг, т.к. в ts структурная типизация, т.е. под сигнатуру interface Props {
readonly value: string;
}
подходит любой объект у которого есть value: string
:const foo = {
value: 'string',
id: 'string'
}
const bar: Props = foo; // ok
const bar: Props = {
value: 'string',
id: 'string' // err
};
Но это специальный случай - предполагается, что задавая литерал вы хотите задать именно объект указанного типа и никакой другого. Однако к парадигме структурной типизации используемой в ts это отношения не имеет, чисто quality of life фича.interface Props {
readonly value: string;
}
interface Props2 {
readonly value: string;
readonly id?: number;
}
const foo = {
value: 'string',
id: 'string'
}
const bar: Props = foo;
const buz: Props2 = bar;
buz.id?.toFixed(2) // ts ok, runtime error :(
const nodeExternals = require('webpack-node-externals');
{
// ...
externals: [nodeExternals()],
}
undefined
не может быть ключом в принципе.card = card_id && this.cards[card_id];
card = this.cards[card_id!];
card = this.cards[String(card_id)];
interface CSS {
[k: string]: {
[k: string]: string | number
}
}
const css = {
default: {
color: '#676767',
border: '1px solid',
border_color: '#C4C4C4',
border_radius: '110px',
padding: '16px 21px',
}
} satisfies CSS;
paths
в tsconfig
- это чисто справочная информация для подсветки, добавленная из расчёта, что вы уже используете какой-то сборщик который такие пути умеет. type Returns<T extends readonly Function[]> = {
-readonly [K in keyof T]: T[K] extends (...args: any[]) => PromiseLike<infer R> ? R : never;
};
type Arguments<T extends readonly Function[]> = {
[K in keyof T]?: T[K] extends (args: infer R, ...a: any[]) => any ? R : never;
};
function fetchAll<T extends readonly Function[]>(functions: readonly [...T], data?: Arguments<T>): Promise<Returns<T>> {
return Promise.all(
functions.map((func, index) => func(data?.[index]))
) as Promise<Returns<T>>;
}
const x = fetchAll([
(a:66) => Promise.resolve(42),
(f:string) => Promise.resolve('hello'),
() => Promise.resolve(true),
], [66, '1ff']);
const arr = [
(a:66) => Promise.resolve(42),
(f:string) => Promise.resolve('hello'),
() => Promise.resolve(true),
] as const;
const x = fetchAll(arr, [66, '1ff']);
next-auth
.skipLibCheck
в tsconfig
. typecript
, или старую версию модуля, или случайно подключаешь несколько версий модуля одновременно, или ещё много куда менее вероятных вариантов. (item: LinkItem) => void
, а требуется (data: MobileMegaMenuItem | LinkItem) => void,
, т.е. функция которая умеет работать и с тем и с тем. Подразумевается что onClick как раз не умеет и может привести к ошибке, потому и не даёт. export const useOpenMenuByHash = <Data extends MobileMegaMenuItem | LinkItem>(
data: Data[],
action: (data: Data) => void,
actionRoom?: () => void
) => {
//...
};
useOpenMenuByHash(data, onClick); // ok
useOpenMenuByHash(data, onClick as (d: LinkItem | MobileMegaMenuItem) => void);
getFormattedData
тоже должен быть дженерик и собсно его(дженерик) прокидывать в нижестоящие.type Type1 = 1;
type Type2 = 2;
type Type3 = 3;
type ContainsType<T extends UniversalType = UniversalType> = {type: T};
type UniversalType = Type1 | Type2 | Type3;
class Cls {
async getFormattedData<T extends UniversalType>(data: ContainsType<T>): Promise<T> {
const anyDataObject = this.validateData(data);
const result = this.formatDataByType(anyDataObject);
return result;
}
validateData<T extends UniversalType = UniversalType>(data: ContainsType<T>): T {
return data.type
}
formatDataByType<T extends UniversalType = UniversalType>(data: T): T {
return data
}
}
const foo = await new Cls().getFormattedData({type: 2}); // 2
const anyDataObject: Type1 | Type2 | Type3 = ...
if (anyDataObject === 2) {
// тут anyDataObject для ts считается Type2
}
но это уже никак не повлияет на выходной тип.Math.random()
. interface MutableRefObject<T> {
prev: null | HTMLParagraphElement;
}
declare module 'lib-name' {
interface MutableRefObject<T> {
prev: null | HTMLParagraphElement;
}
}
declare module 'lib-name/full/path/to/declaration.ts' {
interface MutableRefObject<T> {
prev: null | HTMLParagraphElement;
}
}
interface MySuperMutableRefObject extends MutableRefObject<T> {
prev?: null | HTMLParagraphElement;
}
if (error.value?.statusCode !== 404)
не гарантирует, что в user
не будет null
, мало ли там ошибка 50х
или даже нет ошибки, а просто сервер глюканул.if (!user) {
throw new Error('empty responce')
}
useFetch
которая внутри себя скастует тип по новому или изменение самого типа useFetch
. const result = (blogPosts as Posts)[props.name]
blogPosts
- нужного типа:// тайпргард: тут проверка что posts действительно Posts;
const isPosts = (posts: unknown): posts is Posts => !!posts
&& typeof posts === 'object'
//&& ... ;
if (!isPosts(blogPosts)) throw new Error('wrong blogPosts');
const result = blogPosts[props.name];
class A { id!: string }
class B { id!: string }
class C {
id!: string;
value!: number;
}
const foo: A = new B(); // ok
const bar: A = new C(); // still ok
unknown
. Функции проверки что неизвестный тип является конкретным называются тайпгарды: function isString(arg: unknown): arg is string {
return typeof arg === 'syting'
}