export type NavDataItem =
| {
type: 'a',
name: string;
link: string;
}
| {
type: 'b',
name: string;
children: NavDataItem[];
};
json
, лучше тыкнуть в консоли на ответе "Copy object" и вставь в любой конвертер, который гуглится по "json to ts", например https://app.quicktype.io/. Так ты точно не ошибёшься, а потом уже можешь уточнить тип руками. unknown
и прогонять через тайпгард, проверяя руками, что он соответствует типу, но это не частая практика, увы. export interface Post {
title: string;
content: Content[]; // мы ждём тут массив, а не кортеж из одного элемента
}
export type TContentType = "text" | "video" | "header" | "code" | "images" | "remark" | "materials";
// базовый интерфейс, чисто для надёжности, никуда не экспортируем
interface IContentBase {
type: TContentType
}
export interface ITextContent extends IContentBase {
type: "text";
value: string;
}
export interface IVideoContent extends IContentBase {
type: "video";
url: string;
}
// ...
export interface IOtherContent extends IContentBase {
type: "header" | "code" | "images" | "remark" | "materials";
}
// делаем union с type как discriminator field
export type Content = ITextContent | IVideoContent | IOtherContent;
const items: Post = {
title: "foo bar",
content: [
{type: "text", value: "lorem 1"},
{type: "video", url: "lorem 2"},
{type: "text", value: "lorem 3"}
// ...
]
};
// используем тайпгард, тайпскрипт недостаточно умный, чтоб вывести Extract<Content, { type: "text" }> в таких случаях
const onlyTextType: ITextContent[] = items.content.filter((it): it is ITextContent => it.type === "text");
// ...
<script>
php файл который сгенерирует простой скрипт устанавливавший заданные константы и в js, условно так: header("Content-Type: application/x-javascript");
define("CONSTANT", 1);
echo 'Object.assign(window,' . json_encode(
get_defined_constants(true)['user']
) . ');';
declare const a: {a: 1, b: 2} | {a: 1};
if ('b' in a) { // ts тут сужает тип до {a: 1, b: 2}
console.log(a.b);
}
$.ajax({
url: "/handlers/barcode.php",
type: "get",
xhrFields: { responseType: 'blob'},
converters: {'* image': true},
data: {
data: 'ABC-abc-1239',
code: 'Code128',
},
success: function(response) {
$('#barcode').html('<img src="' + URL.createObjectURL(response) + '"/>');
},
error: function(xhr) {
console.log('Ошибка запроса')
}
});
fetch('/handlers/barcode.php?data=ABC-abc-1239&code=Code128')
.then(res => res.blob())
.then(URL.createObjectURL)
.then(src => {
$('#barcode > img').attr('src', src)
})
.catch(err => {
console.log('Ошибка запроса')
});
unknown
, и работа с ним исходя из этого, со всеми требуемыми проверками перед какими-либо действиями. UserInfo
обратно совместим с BaseUserInfo
, т.к. для BaseUserInfo.getState()
возвращаемое значение имеет тип void
(не путать с undefined
), который никак не может быть использован (сам ts не даст).abstract class BaseUserInfo {
abstract getState(): void;
}
class UserInfo extends BaseUserInfo {
override getState = (): number => 1;
}
function useInfo(info: BaseUserInfo) {
// An expression of type 'void' cannot be tested for truthiness.(1345)
if (info.getState()) { // не получится так сделать и всё сломать
console.log('never')
}
}
function getCommand(file) {
return import(
/* webpackInclude: /[A-Za-z0-9-_,\s]+\.ts$/i */
`./commands/${file}`
);
}
// какая-то проверка достаточная чтобы сказать, что у нас тут NextPageContext;
const isNextPageContext = (ctx: unknown): ctx is NextPageContext => false;
// аналогично для AppContext
const isAppContext = (ctx: unknown): ctx is AppContext => false;
const baseQuery = fetchBaseQuery({
baseUrl: 'http://localhost:7777/api/auth',
prepareHeaders: (headers, { extra }) => {
let req;
if (isNextPageContext(extra)) {
req = extra.req;
} else if (isAppContext(extra)) {
req = extra.ctx?.req;
}
if (req) {
headers.set('Cookie', req.headers.cookie || '');
}
return headers;
},
credentials: 'include',
});
interface CreateConnectionOptions extends ConnectOptions {
retryCount?: number;
retryDelay?: number;
}
function createConnection(uri: string, {
retryCount = 6,
retryDelay = 1000,
...mongooseConnectOptions
}: CreateConnectionOptions = {}): Observable<Connection> {
let connection$ = defer(() => mongoose.createConnection(uri, mongooseConnectOptions).asPromise());
if (retryCount > 0) {
connection$ = connection$.pipe(retry({
count: retryCount,
delay: retryDelay
}));
}
return connection$.pipe(shareReplay(1));
}