// нужно чтобы возвращало тип функции с последовательно указанными параметрами
type EventReceiver<T> = (...params: T ) => void;
// тестируем
type FeatureOptions0 = EventReceiver<[string, number]>
// возвращает то что нужно - type FeatureOptions0 = (params_0: string, params_1: number) => void
import ExtendEventEmitter from '../libs/class.extend.event.emitter'
type EventMap = Record<string, any>;
type EventKey<T extends EventMap> = string & keyof T;
type EventReceiver<T extends unknown[]> = (...params: T ) => void;
type FeatureOptions0 = EventReceiver<[string, number]>
interface Emitter<T extends EventMap> {
on<K extends EventKey<T>>
(eventName: K, fn: EventReceiver<T[K]>): void;
once<K extends EventKey<T>>
(eventName: K, fn: EventReceiver<T[K]>): void;
off<K extends EventKey<T>>
(eventName: K, fn: EventReceiver<T[K]>): void;
emit<K extends EventKey<T>>
(eventName: K, ...params: T[K]): void;
}
export class MyEmitter<T extends EventMap> implements Emitter<T> {
private emitter = new ExtendEventEmitter();
on<K extends EventKey<T>>(eventName: K, fn: EventReceiver<T[K]>) {
this.emitter.on(eventName, fn);
}
once<K extends EventKey<T>>(eventName: K, fn: EventReceiver<T[K]>) {
this.emitter.once(eventName, fn);
}
off<K extends EventKey<T>>(eventName: K, fn: EventReceiver<T[K]>) {
this.emitter.off(eventName, fn);
}
emit<K extends EventKey<T>>(eventName: K, ...params: T[K]) {
this.emitter.emit(eventName, params);
}
}
const emitter = new MyEmitter<{
data: [string, number];
end: [undefined];
}>();
emitter.on('end', () => {}); // ok
emitter.on('data', (a: string, f:number) => {}); // ok
emitter.on('data', (a: string) => {}); // ok
emitter.on('data', (a: string, f:string) => {}); // error
emitter.on('data', (a: boolean) => {}); // error
emitter.emit('data', 'aaa', 1); // ok
emitter.emit('data', 'aaa'); // error
emitter.emit('data', 'aaa', 'bbb'); // error
Но возможно так делать не принято и сейчас предпочтительнее принципиально другой подход.
, ну и при наличии у вас желания и возможности был бы рад фидбеку по коду (как можно делать, и как лучше не делать).
on: Emitter<T>['on'] = (eventName, fn) => {
this.emitter.on(eventName, fn);
}
end: [undefined];
end: [undefined];
declare type EventName = 'string'
declare type EventKey = function(initType, itemType){
// обычный js работающий с обычными переменными initType, itemType и формирующий результат
}
declare type EventReceiver = (initType, itemType)=>{
// обычный js работающий с обычными переменными initType, itemType и формирующий результат
}
declare type ListenerParams = (initType, itemType, itemIndex,...,eventName)=>{
// обычный js работающий с обычными переменными initType, itemType, itemIndex, eventName и формирующий результат
}
declare type EmiterEvents = {
data: [string, number],
end: []
}
export class MyEmitter{
private emitter = new ExtendEventEmitter();
on(eventName: EventName, fn: EventReceiver) {...}
emit(eventName: EventName, ...params: ListenerParams(eventName)) {...}
...
}
const emitter = new MyEmitter: EmiterEvents ();
type HelloWorld = string
import type { Equal, Expect, NotAny } from './test-utils'
.export type IsAny<T> = 0 extends 1 & T ? true : false
test-utils
, была дана ссылка https://stackoverflow.com/questions/49927523/disal..., в которой все разжевано.export type IsAny<T> = 0 extends 1 & T ? true : false
0 extends 1
extends здесь не расширение нуля еденицей а проверка является ли ноль подмножеством множества единица? (Все что нашел про extends в TS https://metanit.com/web/typescript/3.2.php, но оно немного не вяжется у меня в голове с вышеуказанным применением)В общем такой вопрос возник, стоит ли по вашему мнению на этапе прохождения челенджа загоняться и для более глубокого погружения ковырять все эти файлы с утилитами и прочим из состава type-challenges или в процессе прохождения челенжа все эти моменты будут раскрыты в самих заданиях?
1. 0 extends 1 extends здесь не расширение нуля еденицей а проверка является ли ноль подмножеством множества единица? (Все что нашел про extends в TS https://metanit.com/web/typescript/3.2.php, но оно немного не вяжется у меня в голове с вышеуказанным применением)
2. что у extends приоритет меньше чем у &? (где можно почитать какие операторы и используются в объявлении типов и о правилах их применения)
0 = 1 + Т
. Ну и проверка эта на эни, потому что всё, к чему прикасается эни, становится эни, а если попробовать запихнуть любой другой тип, там уже будет не эни. В целом, единицу можно заменить вообще на что угодно, кроме нуля. И эни. И анноун. И невер. И намбер. Короче, что угодно, кроме того, от чего может наследоваться 0. Да и нуль тоже можно заменить.)И да, пожалуйста, давай на "ты".) А то начинаю чувствовать себя мудрым старцем.)
type arr1 = ['a', 'b', 'c']
type arr2 = [3, 2, 1]
type tail1 = Last<arr1> // expected to be 'c'
type tail2 = Last<arr2> // expected to be 1
type Last<T extends any[]> = [any,...T][T['length']]
type Last<T extends any[]> = T extends [...any, infer R] ? R : never;