class Foo {
a!: number;
b!: number;
}
function bar(arg:Foo) {};
const randomObj = {a:1, b:2, c:5};
bar(randomObj); // ok
match
может вернуть null
и тогда произойдёт ошибка во время исполнения.const [a, b, c, d, f, g= ''] = value.match(/\d+/g) || [];
Либо, если ты на 146% уверен, что match
обязательно что-нибудь найдёт: const [a, b, c, d, f, g= ''] = value.match(/\d+/g) as string[];
Иначе зачем вообще нужны алиасы в ts?
paths
запилили, чтобы отразить поведение модных сборщиков, типа webpack, а не наоборот. Т.е. предполагается, что paths
используются только когда уже есть сборщик который осуществляет всю логику, а не как первичный источник конфигурации. class A {
static bool: boolean = true;
}
class B extends A {
static readonly bool = true;
}
class C extends A {
static readonly bool = false;
}
function func<T extends typeof A, P = T['bool'] extends true ? number : string>(param: P) { }
func<typeof B>(123); //ok
func<typeof B>('random string'); //not ok
func<typeof C>(123); //not ok
func<typeof C>('random string'); //ok
const elementDefaults = {
'welcome': {
placeholder: 'Type welcome message...',
question: '',
isDescription: false,
description: '',
startButtonText: 'Start',
},
'checkbox': {
placeholder: 'Type question or statement...',
question: '',
isDescription: false,
description: '',
options: [] as string[],
multiple: false,
},
'dropdown': {
placeholder: 'Type question here...',
question: '',
isDescription: false,
description: '',
options: [] as string[],
},
'rating': {
placeholder: 'Type question...',
question: '',
isDescription: false,
description: '',
steps: 10,
defaultRate: 0,
shape: 'stars',
},
'text': {
placeholder: 'Type question...',
question: '',
isDescription: false,
description: '',
maxLength: 99999,
},
'slider': {
placeholder: 'Type question...',
question: '',
isDescription: false,
description: '',
steps: 10,
},
'thanks': {
placeholder: 'Type message...',
question: '',
isDescription: false,
description: '',
}
}
export function getElementSettings<E extends keyof typeof elementTypes>(type: E) {
if(!(type in elementDefaults)) throw new Error("element type doesn't match!");
return elementDefaults[type];
}
type ElementSetting = {
placeholder: string;
question: string;
isDescription: boolean;
description: string;
}
type ElementSettings = {
welcome: ElementSetting & {
startButtonText: string;
},
checkbox: ElementSetting & {
options: string[];
multiple: boolean;
},
dropdown: ElementSetting & {
options: string[];
},
rating: ElementSetting & {
steps: number;
defaultRate: number;
shape: string;
},
text: ElementSetting & {
maxLength: number;
},
slider: ElementSetting & {
steps: number;
},
thanks: ElementSetting
}
const elementDefaults: ElementSettings = {
'welcome': {
placeholder: 'Type welcome message...',
question: '',
isDescription: false,
description: '',
startButtonText: 'Start',
},
'checkbox': {
placeholder: 'Type question or statement...',
question: '',
isDescription: false,
description: '',
options: [],
multiple: false,
},
'dropdown': {
placeholder: 'Type question here...',
question: '',
isDescription: false,
description: '',
options: [],
},
'rating': {
placeholder: 'Type question...',
question: '',
isDescription: false,
description: '',
steps: 10,
defaultRate: 0,
shape: 'stars',
},
'text': {
placeholder: 'Type question...',
question: '',
isDescription: false,
description: '',
maxLength: 99999,
},
'slider': {
placeholder: 'Type question...',
question: '',
isDescription: false,
description: '',
steps: 10,
},
'thanks': {
placeholder: 'Type message...',
question: '',
isDescription: false,
description: '',
}
}
export function getElementSettings<E extends keyof ElementSettings>(type: E): ElementSettings[E] {
if(!(type in elementDefaults)) throw new Error("element type doesn't match!");
return elementDefaults[type];
}
ts-node
в tsconfig.json
: {
"ts-node": {
"compilerOptions": {
"module": "CommonJS"
}
},
...
}
classes[item]
.for(let item in classes) {
classes[item as keyof typeof classes] = 'page'+item
}
В typescript специально не добавили автоматическую типизацию ключей оставив просто string
, так как из-за его структурной природы нельзя наверняка сказать, есть ли в полученном объекте(или его прототипе) ещё какие-то ключи, кроме тех, что указаны в его типе, и, соответственно, нельзя быть уверенным, что ничего не сломается. map
складывает в выходной массив результат переданной функции. Поскольку она у вас возвращает отфильтрованный массив items
, то в итоге у вас получается массив массивов items
. Если вам нужно, чтоб возвращались категории - возвращайте категории.reduce
: сonst filterData = filter(arr, input.value);
interface Category {
category: string;
list: Array<{
item: string;
}>;
}
function filter<T extends Category>(data: T[], value: string): T[] {
if (!value) return data.slice(); // или [] если при пустом value нужен пустой массив
value = value.toLowerCase();
return data.reduce((result, category) => {
if(category.category.toLowerCase().includes(value)) {
result.push(category);
} else {
const list = category.list.filter(({ item }) => item.toLowerCase().includes(value));
if (list.length) {
result.push({
...category,
list
});
}
}
return result;
}, [] as T[])
}
async
и await
, они здесь не нужны:const ApiServiceModule = {
get: <T>(url: string): Promise<T> => fetch(url)
.then(response => response.json())
.catch(err => console.error(err))
}
async
/await
всего лишь сахар над Promise
и в данном случае ничего не делают, т.к fetch
и так возвращает Promise
.this
. function wrapper<T extends { start(...args: unknown[]): unknown }>(target: { new(): T }, ...args: Parameters<T['start']>): T {
let instance = new target();
instance.start(...args);
return instance;
}
class RandomClass {
start(arg1: string, arg2: number) { /* ... */ }
}
let instance = wrapper(RandomClass, 'Hello, world!', 777); /// все ок
let instance2 = wrapper(RandomClass, 777); /// ошибка
type TupleUnion<U extends string, R extends string[] = []> = {
[S in U]: Exclude<U, S> extends never ? [...R, S] : TupleUnion<Exclude<U, S>, [...R, S]>;
}[U] & string[];
interface Interface {
foo: boolean;
bar: string;
baz: object
}
type Keys = TupleUnion<keyof Interface>;
let keys: Keys;
keys = ['foo', 'bar', 'baz']; // OK все ключи указаны
keys = ['foo']; // NOT OK указаны не все ключи
keys = ['foo', 'bar', 'another bar']; // NOT OK один из ключей не совпадает