Можно ли обойтись обычным js?Можно. TypeScript лишь добавляет к JavaScript статическую типизацию в компайл-тайм. После компиляции будет все тот же JS.
Какие будут плюсы?Главный плюс, ИМХО, - скорость разработки за счет подсказок IDE и автодополнения, больше авторефакторингов. Ну и возможность ограничить использование функций/методов от нежелательного использования тоже плюс. А если еще и проектировать доменную модель на типах, то можно сразу видеть, если что-то не сходится, еще до написания логики.
Не будет ли много лишней писанины по сравнению с чистым js?Большинство типов TypeScript способен вывести. Далеко не Хиндли-Милнер конечно, но тоже хорошо. Я пишу больше в ФП стиле, с редкой примесью структурно-процедурного при описании эффектов, так у меня явные указания типов присутствуют только в сигнатурах функций. В самой логике код неотличим от обычного JS, но с хорошей проверкой типов.
Будет ли сложно хранить скомпилированный js?Как и любые другие артефакты сборки, скомпилированный JS хранить не нужно. Компилируйте непосредственно перед выкладыванием на продакшен, а в git храните лишь TS код + настройки компилятора. А в dev среде вообще можно запускаться через модуль ts-node.
type Validator<U extends string, A extends ReadonlyArray<string>> =
(U extends A[number] ? true : false) extends true ? A : never;
type U = 'foo' | 'bar';
const arr0 = ['foo'] as const;
const arr1 = ['bar'] as const;
const arr2 = ['foo', 'bar'] as const;
type A0 = Validator<U, typeof arr0>; // never
type A1 = Validator<U, typeof arr1>; // never
type A2 = Validator<U, typeof arr2>; // readonly ['foo', 'bar']
const _check0: A0 = arr0; // error
const _check1: A1 = arr1; // error
const _check2: A2 = arr2;
async function checkUser(login, password) {
const ad = new ActiveDirectory(ad_config)
const auth = await new Promise((resolve, reject) => {
ad.authenticate(login, password, (err, auth) => {
if (err) {
return reject(err)
}
resolve(auth)
})
})
return auth
}
const elementSettings = {
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: '',
}
} as const;
type Editable<T> = { -readonly [P in keyof T]: T[P]; };
type ElementSettings = typeof elementSettings;
export function getElementSettings<T extends keyof ElementSettings>(type: T): Editable<ElementSettings[T]> {
if(type in elementSettings) {
const settings = {...elementSettings[type]};
if('options' in settings) {
(settings as {options: string[]}).options = (settings as {options: string[]}).options.slice();
}
return settings;
}
throw new Error("element type doesn't match!");
}
mport React from 'react';
import { render } from 'react-dom';
type ITableColumn<D extends Record<string, any>> = {
property: string;
format?: (value: any, item: D) => React.ReactNode | string | number;
header?: any;
footer?: any;
};
type ITable<T extends Record<string, any>, D extends Record<string, any>> = {
isLoading?: boolean;
columns: ITableColumn<D>[];
rows: Array<T>;
};
type IContext<D extends Record<string, any>> = {
rows: any;
columns: ITableColumn<D>[];
};
const getColumns = <D extends Record<string, any>>(): ITableColumn<D>[] => [
{
property: 'name',
format: (value, item) => {
const { lastName } = item;
return `${value} ${lastName}`;
},
header: 'heade',
footer: 'footer'
},
{
property: 'count',
header: 'heade',
footer: 'footer'
}
]
interface AppProps { }
interface AppState {
name: string;
}
const Table:React.FC<ITable> = ({ isLoading, columns, rows }) => {
return <h1>table</h1>
}
const App = () => (
<div>
<Table
columns={getColumns()}
rows={[
{ name: 'userName 0', lastName: 'userLastName 0', count: 10 },
{ name: 'userName 1', lastName: 'userLastName 1', count: 20 },
{ name: 'userName 2', lastName: 'userLastName 2', count: 30 },
]}
/>
<p>Start editing to see some magic happen :)</p>
</div>
);
render(<App />, document.getElementById('root'));
import type {ComponentType} from 'react';
import {Button} from 'react-native';
type InferProps<Component> = Component extends ComponentType<infer Props> ? Props : never;
const MyButton = (props: InferProps<typeof Button>) => {
return <Button title={props.title} onPress={props.onPress} style={{color:'#fff'}} />
}
Подойдет ли тут многопоточность или я что то путаю?В JS нет многопоточности.
Как это реализовать? С помощью чего?Просто отправить несколько запросов сразу. Запросы работают асинхронно и не блокируют поток выполнения.
struct android_app *
- это возвращаемый функцией тип;(void)
после имени означает, что функция без аргументов, современные компиляторы позволяют писать просто пустые скобки ()
;// описание структуры android_app должно быть выше заголовка его использующего,
// иначе он будет невалидным. А вот описание полей (реализация) может быть и ниже
struct android_app;
struct android_app* GetAndroidApp();
комментарии говорится что я могу добавить его в HeaderЭто значит, что данные сигнатуры можно вынести в заголовочный файл (тот что с расширением .h), это позволит вставить его во множество исходников через директиву препроцессора #include
routes.map((route: IPrivateRoute | IRoute) => route.access // Здесь ошибка, так как в IRoute нет поля access, а значит нет и в юнионе IPrivateRoute | IRoute
? <PrivateRoute key={route.path} {...route}/> // а здесь, так как route.access не является тайп-гвардом, и не смотря на условие, тип по прежнему IPrivateRoute | IRoute
// запомнили в x значение 0
x = 0;
// запомнили в y значение -200
y = -200;
// тут выражение из нескольких действий
x = 0 * x + 1 * y
// 1. вместо переменных подставим значения
// 0 * 0 + 1 * -200
// 2. посчитаем умножения
// 0 + -200
// 3. посчитаем сложения
// -200
// запомним -200 в x
// на этом этапе у нас в x запомнено -200 и в y тоже -200
// с этим проделайте по аналогии
y = -1 * x + 0 * y
function render(message) {
const p = document.createElement("p"); // создали p, его еще нигде нет в DOM, все ok
p.textContent = message;
windowChatUser1.append(p); // поместили наш p в windowChatUser1, с этого момента он есть в DOM
windowChatUser2.append(p); // переместили наш p в windowChatUser2
}
логично, что из windowChatUser1 наш p исчез при перемещении в windowChatUser2, так как один элемент не может быть в двух родителях сразуwindowChatUser2.append(p.cloneNode(true));
.slider__slide {
/* изменяем внешний контейнер на viewport величины */
height: 100vh;
width: 100vw;
}
/* прописываем высоту внутренним контейнерам */
.slick-list, .slick-track {
height: 100%;
}
const ApiServiceModule = {
get: (url: string): Promise<unknown> => fetch(url)
.then(response => response.json())
.catch(err => console.error(err))
}
if (document.URL.indexOf("/testurl/") != -1);
if обрабатывает пустую операцию, все что дальше уже вне if// проиндексируем по ключам
const [rootIndex, idIndex] = array.reduce(([roots, ids], obj) => {
(roots[obj.root_id] ??= []).push(obj);
ids[obj.id] = obj;
return [roots, ids];
}, [{}, {}]);
// и найдем по нему нужные объекты:
const objectsWithoutExistingParent = Object.keys(rootIndex).filter(key => !idIndex.hasOwnProperty(key)).flatMap(key => rootIndex[key]);
console.log(objectsWithoutExistingParent);