"plugin:@typescript-eslint/recommended"
, то не нужен, он просто там уже прописан.recommended
и ты можешь его выкинуть, набросав свой по вкусу. И тогда всё сломается. Потому лучше указывать парсер сразу явно. Promise.reslove(data)
и Promise.reject(error)
, а во-вторых: при возврате из then
\catch
даже они не нужны. interface ResponseData {
status: boolean;
data?: object;
}
function sendQuery(url: string, data: object): Promise<ResponseData> {
return fetch(url, {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify(data)
}).then(response =>
response.json()
).then(data => ({
status: true,
data: data
})).catch(() => {
throw {
status: false
}
});
}
new Promise
, а потому выдаёт Promise<unknown>
. Т.е. каждый раз, когда вы используете new Promise
- надо использовать его с дженериком: new Promise<Type>
. const queryKey: AuthMessagesKeys = queryObject.message
function isAuthMessagesKey(str: string): str is AuthMessagesKeys {
return ['login', 'logout', 'session'].includes(str);
}
PropsWithChildren<Props>
. Но под капотом он просто делает так: type PropsWithChildren<P> = P & { children?: ReactNode };
type TwitterProps = {
children: (user: string) => ReactNode
}
const response: ITwitter = ...
. Только если какая-нить хрень прилетит то может сломаться в рантайме, так что либо ты доверяешь серверу, либо используешь какую-нить либу для дополнительной проверки вживую.) type WritableFields<T> = Partial<Pick<T, WritableKeys<T>>>;
export function createElement<K extends keyof HTMLElementTagNameMap>(tag: K, options?: WritableFields<HTMLElementTagNameMap[K]>): HTMLElementTagNameMap[K] {
let element = document.createElement(tag)
if (options) {
// assign options
Object.assign(element, options);
}
return element
}
type WritableFields<T> = Partial<Pick<T, WritableKeys<T>>>;
export function createElement<K extends keyof HTMLElementTagNameMap>(tag: K, options?: WritableFields<HTMLElementTagNameMap[K]>): HTMLElementTagNameMap[K] {
let element = document.createElement(tag)
if (options) {
// assign options
let option: keyof typeof options;
for (option in options) {
element[option] = options[option]!; // ! - потому что теоретически ты можешь передать undefined явно, но морочиться с этим не стоит
}
}
return element
}
interface Foo {
foo: number;
}
тебе ничего не мешает передать ему {
foo: 1,
bar: 2
}
, т.к. данный объект расширяет интерфейс Foo и, соответственно, удовлетворяет ему. Получается, что внутри функции typescript никак не может быть уверен, что ключи указанные в интерфейсе - это ВСЕ ключи, а значит не может быть уверен, что при переборе и присвоении не будет присвоено что-то лишнее. (Это не говоря уже о прототипах, геттерах и прочем) Vue
появились дополнительные свойства типа $route
. Надо отдельно подключать декларации вручную, либо следовать инструкции выше. interface Volume {
id: number;
volume?: string;
}
interface Snapshot {
id: number;
snapshot?: string;
}
А так нет:interface Volume {
id: number;
volume: string;
}
interface Snapshot {
id: number;
snapshot: string;
}
interface Volume {
id?: number;
}
interface Snapshot {
id?: string;
}
enum Constants {
VERTICAL = 'vertical',
STEP = 'step'
}
interface ConstantsTypes {
[Constants.VERTICAL]: boolean,
[Constants.STEP]: number,
}
public get<T extends keyof ConstantsTypes>(prop: T): ConstantsTypes[T] {}
export class IResultItem {
constructor(
public id: i32,
public type: string,
public date: string,
public from: string,
public from_id: i32,
public text: string
) {}
}
export function add(
result: IResultItem[] = [new IResultItem( 1, "type", "25.25.2025", "rew", 123, "hello" )]
): IResultItem[] {
return result;
}
type ClearIndex<T> = {
[ P in keyof T as string extends P ? never : P ] : T[P]
};
class FOO implements ClearIndex<Service_FOO > {
methodFoo() {}
}
Record<string, () => void>
имеет "index signature", т.е. заявляет, что обращение по любому ключу string
вернёт () => void
. Service_FOO
расширяет этот тип(а не сужает), потому Service_FOO
имеет ту же index signature и уточнённый конкретный метод. let a1 = {
channelID: {
RegExp: ["\\d+", true],
description: "d1"
},
content: {
RegExp: [".+", true],
description: "d2"
}
};
type T1 = {[K in keyof typeof a1]: string}
type Args = {
[key: string]: {
RegExp: [string, boolean],
description: string
}
}
function createArgs<T extends Args>(args: T): T {
return args;
}
type TStringKeys<T extends Args> = {[K in keyof T]: string};
let a1 = createArgs({
channelID: {
RegExp: ["\\d+", true],
description: "d1"
},
content: {
RegExp: [".+", true],
description: "d2"
}
});
type T1 = TStringKeys<typeof a1>
К сожалению на текущий момент(ts4.2.3) избавиться от функции-обёртки не получится. interface IOrder {
date: string,
docTypesName: string,
docId: number,
image: string,
name: string,
price: number,
quantity: number,
removed: number,
}
interface IProduct {
image: string,
name: string,
price: number,
quantity: number,
}
interface IDocument {
date: string,
docId: number,
docTypesName: string,
products: IProduct[],
}
interface IElement {
date: string,
documents: IDocument[]
}
interface IElementMap {
date: string,
documents: Record<string, IDocument>
}
type IResultMap = Record<string, IElementMap>;
function f(orders: IOrder[]): IElement[] {
const result = orders.reduce((accumulator, currentValue) => {
const date = currentValue.date.split(' ')[0];
if (!accumulator[date]) {
accumulator[date] = {
date,
documents: {},
}
}
if (!accumulator[date].documents[currentValue.docTypesName]) {
accumulator[date].documents[currentValue.docTypesName] = {
date: currentValue.date,
docId: currentValue.docId,
docTypesName: currentValue.docTypesName,
products: [],
}
}
accumulator[date].documents[currentValue.docTypesName].products.push({
name: currentValue.name,
price: currentValue.price,
image: currentValue.image,
quantity: currentValue.quantity,
})
return accumulator;
}, {} as IResultMap)
console.log('result', result);
return Object.values(result).map(currentValue => {
console.log('currentValue', currentValue);
return {
...currentValue,
documents: Object.values(currentValue.documents)
}
});
}
console.log(f(orders));