mirror of https://github.com/zulip/zulip.git
tsconfig: Enable exactOptionalPropertyTypes.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
parent
08a50cf74b
commit
507eb4913c
|
@ -22,6 +22,7 @@
|
|||
|
||||
/* Strict type-checking */
|
||||
"strict": true,
|
||||
"exactOptionalPropertyTypes": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"isolatedModules": true,
|
||||
"noImplicitOverride": true,
|
||||
|
|
|
@ -13,7 +13,7 @@ export default class DebugRequirePlugin implements WebpackPluginInstance {
|
|||
const resolved = new Map<string, Set<string>>();
|
||||
const nameSymbol = Symbol("DebugRequirePluginName");
|
||||
type NamedRequest = ResolveRequest & {
|
||||
[nameSymbol]?: string;
|
||||
[nameSymbol]?: string | undefined;
|
||||
};
|
||||
let debugRequirePath: string | false = false;
|
||||
|
||||
|
|
|
@ -628,9 +628,9 @@ export async function run_test_async(test_function: (page: Page) => Promise<void
|
|||
columnNumber,
|
||||
}: ConsoleMessageLocation): Promise<string> => {
|
||||
let frame = new StackFrame({
|
||||
fileName: url,
|
||||
lineNumber: lineNumber === undefined ? undefined : lineNumber + 1,
|
||||
columnNumber: columnNumber === undefined ? undefined : columnNumber + 1,
|
||||
...(url !== undefined && {fileName: url}),
|
||||
...(lineNumber !== undefined && {lineNumber: lineNumber + 1}),
|
||||
...(columnNumber !== undefined && {columnNumber: columnNumber + 1}),
|
||||
});
|
||||
try {
|
||||
frame = await gps.getMappedLocation(frame);
|
||||
|
|
|
@ -28,11 +28,11 @@ type NumberedLine = {
|
|||
};
|
||||
|
||||
type CleanStackFrame = {
|
||||
full_path?: string;
|
||||
show_path?: string;
|
||||
function_name?: FunctionName;
|
||||
line_number?: number;
|
||||
context?: NumberedLine[];
|
||||
full_path: string | undefined;
|
||||
show_path: string | undefined;
|
||||
function_name: FunctionName | undefined;
|
||||
line_number: number | undefined;
|
||||
context: NumberedLine[] | undefined;
|
||||
};
|
||||
|
||||
export function exception_msg(
|
||||
|
|
|
@ -215,7 +215,7 @@ export class Typeahead<ItemType extends string | object> {
|
|||
dropup: boolean;
|
||||
automated: () => boolean;
|
||||
trigger_selection: (event: JQuery.KeyDownEvent) => boolean;
|
||||
on_escape?: () => void;
|
||||
on_escape: (() => void) | undefined;
|
||||
// returns a string to show in typeahead header or false.
|
||||
header_html: () => string | false;
|
||||
// returns a string to show in typeahead items or false.
|
||||
|
@ -224,16 +224,16 @@ export class Typeahead<ItemType extends string | object> {
|
|||
query = "";
|
||||
mouse_moved_since_typeahead = false;
|
||||
shown = false;
|
||||
openInputFieldOnKeyUp?: () => void;
|
||||
closeInputFieldOnHide?: () => void;
|
||||
openInputFieldOnKeyUp: (() => void) | undefined;
|
||||
closeInputFieldOnHide: (() => void) | undefined;
|
||||
helpOnEmptyStrings: boolean;
|
||||
tabIsEnter: boolean;
|
||||
naturalSearch: boolean;
|
||||
stopAdvance: boolean;
|
||||
advanceKeyCodes: number[];
|
||||
parentElement?: string;
|
||||
parentElement: string | undefined;
|
||||
values: WeakMap<HTMLElement, ItemType>;
|
||||
instance?: Instance;
|
||||
instance: Instance | undefined;
|
||||
|
||||
constructor(input_element: TypeaheadInputElement, options: TypeaheadOptions<ItemType>) {
|
||||
this.input_element = input_element;
|
||||
|
|
|
@ -204,7 +204,7 @@ export function get_title_data(
|
|||
is_group: boolean,
|
||||
): {
|
||||
first_line: string;
|
||||
second_line?: string;
|
||||
second_line: string | undefined;
|
||||
third_line: string;
|
||||
show_you?: boolean;
|
||||
} {
|
||||
|
|
|
@ -14,17 +14,19 @@ import * as spectators from "./spectators";
|
|||
type AjaxRequestHandlerOptions = Omit<JQuery.AjaxSettings, "success"> & {
|
||||
url: string;
|
||||
ignore_reload?: boolean;
|
||||
success?: (
|
||||
success?:
|
||||
| ((
|
||||
data: unknown,
|
||||
textStatus: JQuery.Ajax.SuccessTextStatus,
|
||||
jqXHR: JQuery.jqXHR<unknown>,
|
||||
) => void;
|
||||
) => void)
|
||||
| undefined;
|
||||
error?: JQuery.Ajax.ErrorCallback<unknown>;
|
||||
};
|
||||
|
||||
type PatchRequestData =
|
||||
| {processData: false; data: FormData}
|
||||
| {processData?: true; data: Record<string, unknown>};
|
||||
| {processData?: true | undefined; data: Record<string, unknown>};
|
||||
|
||||
export type AjaxRequestHandler = typeof call | typeof patch;
|
||||
|
||||
|
|
|
@ -33,14 +33,14 @@ type ComposeActionsStartOpts = {
|
|||
force_close?: boolean;
|
||||
trigger?: string;
|
||||
private_message_recipient?: string;
|
||||
message?: Message;
|
||||
stream_id?: number;
|
||||
message?: Message | undefined;
|
||||
stream_id?: number | undefined;
|
||||
topic?: string;
|
||||
content?: string;
|
||||
draft_id?: string;
|
||||
skip_scrolling_selected_message?: boolean;
|
||||
is_reply?: boolean;
|
||||
keep_composebox_empty?: boolean;
|
||||
keep_composebox_empty?: boolean | undefined;
|
||||
};
|
||||
|
||||
// An iteration on `ComposeActionsStartOpts` that enforces that
|
||||
|
|
|
@ -18,9 +18,9 @@ function format_stream_recipient_label(stream_id: number, topic: string): string
|
|||
}
|
||||
|
||||
type ComposeClosedMessage = {
|
||||
stream_id?: number;
|
||||
stream_id?: number | undefined;
|
||||
topic?: string;
|
||||
display_reply_to?: string;
|
||||
display_reply_to?: string | undefined;
|
||||
};
|
||||
|
||||
export function get_recipient_label(message?: ComposeClosedMessage): string {
|
||||
|
|
|
@ -146,8 +146,8 @@ export function respond_to_message(opts: {
|
|||
message_type: msg_type,
|
||||
stream_id,
|
||||
topic,
|
||||
private_message_recipient: pm_recipient,
|
||||
trigger: opts.trigger,
|
||||
...(pm_recipient !== undefined && {private_message_recipient: pm_recipient}),
|
||||
...(opts.trigger !== undefined && {trigger: opts.trigger}),
|
||||
is_reply: true,
|
||||
keep_composebox_empty: opts.keep_composebox_empty,
|
||||
});
|
||||
|
|
|
@ -31,7 +31,7 @@ export type ComposeTriggeredOptions = {
|
|||
| {
|
||||
message_type: "stream";
|
||||
topic: string;
|
||||
stream_id?: number;
|
||||
stream_id?: number | undefined;
|
||||
}
|
||||
| {
|
||||
message_type: "private";
|
||||
|
|
|
@ -555,7 +555,7 @@ type FormattedDraft =
|
|||
| {
|
||||
is_stream: true;
|
||||
draft_id: string;
|
||||
stream_name?: string;
|
||||
stream_name?: string | undefined;
|
||||
recipient_bar_color: string;
|
||||
stream_privacy_icon_color: string;
|
||||
topic: string;
|
||||
|
|
|
@ -59,7 +59,7 @@ type DropdownWidgetOptions = {
|
|||
focus_target_on_hidden?: boolean;
|
||||
tippy_props?: Partial<tippy.Props>;
|
||||
// NOTE: Any value other than `undefined` will be rendered when class is initialized.
|
||||
default_id?: string | number;
|
||||
default_id?: string | number | undefined;
|
||||
unique_id_type?: DataTypes;
|
||||
// Text to show if the current value is not in `get_options()`.
|
||||
text_if_current_value_not_in_options?: string;
|
||||
|
|
|
@ -243,7 +243,7 @@ function message_matches_search_term(message: Message, operator: string, operand
|
|||
|
||||
export class Filter {
|
||||
_terms: NarrowTerm[];
|
||||
_sub?: StreamSubscription;
|
||||
_sub?: StreamSubscription | undefined;
|
||||
_sorted_term_types?: string[] = undefined;
|
||||
_predicate?: (message: Message) => boolean;
|
||||
_can_mark_messages_read?: boolean;
|
||||
|
@ -914,8 +914,8 @@ export class Filter {
|
|||
|
||||
add_icon_data(context: {
|
||||
title: string;
|
||||
description?: string;
|
||||
link?: string;
|
||||
description?: string | undefined;
|
||||
link?: string | undefined;
|
||||
is_spectator: boolean;
|
||||
}): IconData {
|
||||
// We have special icons for the simple narrows available for the via sidebars.
|
||||
|
|
|
@ -860,7 +860,7 @@ function update_closed_compose_text($row: JQuery, is_header_row: boolean): void
|
|||
compose_closed_ui.update_reply_recipient_label(message);
|
||||
}
|
||||
|
||||
export function get_focused_row_message(): {message?: Message} & (
|
||||
export function get_focused_row_message(): {message?: Message | undefined} & (
|
||||
| {msg_type: "private"; private_message_recipient?: string}
|
||||
| {msg_type: "stream"; stream_id: number; topic?: string}
|
||||
| {msg_type?: never}
|
||||
|
@ -893,6 +893,7 @@ export function get_focused_row_message(): {message?: Message} & (
|
|||
const message = message_store.get(row_info.latest_msg_id);
|
||||
if (message === undefined) {
|
||||
const recipients = people.user_ids_string_to_emails_string(row_info.user_ids_string);
|
||||
assert(recipients !== undefined);
|
||||
return {
|
||||
msg_type: "private",
|
||||
private_message_recipient: recipients,
|
||||
|
|
|
@ -17,7 +17,7 @@ export type InputPillItem<T> = {
|
|||
type: string;
|
||||
img_src?: string;
|
||||
deactivated?: boolean;
|
||||
status_emoji_info?: EmojiRenderingDetails & {emoji_alt_code?: boolean}; // TODO: Move this in user_status.js
|
||||
status_emoji_info?: (EmojiRenderingDetails & {emoji_alt_code?: boolean}) | undefined; // TODO: Move this in user_status.js
|
||||
should_add_guest_user_indicator?: boolean;
|
||||
} & T;
|
||||
|
||||
|
@ -58,11 +58,11 @@ type InputPillStore<T> = {
|
|||
type InputPillRenderingDetails = {
|
||||
display_value: string;
|
||||
has_image: boolean;
|
||||
img_src?: string;
|
||||
deactivated?: boolean;
|
||||
img_src?: string | undefined;
|
||||
deactivated: boolean | undefined;
|
||||
has_status?: boolean;
|
||||
status_emoji_info?: EmojiRenderingDetails & {emoji_alt_code?: boolean};
|
||||
should_add_guest_user_indicator?: boolean;
|
||||
status_emoji_info?: (EmojiRenderingDetails & {emoji_alt_code?: boolean}) | undefined;
|
||||
should_add_guest_user_indicator: boolean | undefined;
|
||||
};
|
||||
|
||||
// These are the functions that are exposed to other modules.
|
||||
|
|
|
@ -14,7 +14,7 @@ type List<Key> = {
|
|||
export class ListCursor<Key> {
|
||||
highlight_class: string;
|
||||
list: List<Key>;
|
||||
curr_key?: Key;
|
||||
curr_key?: Key | undefined;
|
||||
|
||||
constructor({highlight_class, list}: {highlight_class: string; list: List<Key>}) {
|
||||
this.highlight_class = highlight_class;
|
||||
|
|
|
@ -11,7 +11,12 @@ export function make_indicator(
|
|||
text,
|
||||
width,
|
||||
height,
|
||||
}: {abs_positioned?: boolean; text?: string; width?: number; height?: number} = {},
|
||||
}: {
|
||||
abs_positioned?: boolean;
|
||||
text?: string;
|
||||
width?: number | undefined;
|
||||
height?: number | undefined;
|
||||
} = {},
|
||||
): void {
|
||||
let $container = $outer_container;
|
||||
|
||||
|
|
|
@ -30,15 +30,15 @@ type EditHistoryEntry = {
|
|||
edited_by_notice: string;
|
||||
timestamp: number; // require to set data-message-id for overlay message row
|
||||
is_stream: boolean;
|
||||
recipient_bar_color?: string;
|
||||
body_to_render?: string;
|
||||
topic_edited?: boolean;
|
||||
prev_topic?: string;
|
||||
new_topic?: string;
|
||||
stream_changed?: boolean;
|
||||
prev_stream?: string;
|
||||
prev_stream_id?: number;
|
||||
new_stream?: string;
|
||||
recipient_bar_color: string | undefined;
|
||||
body_to_render: string | undefined;
|
||||
topic_edited: boolean | undefined;
|
||||
prev_topic: string | undefined;
|
||||
new_topic: string | undefined;
|
||||
stream_changed: boolean | undefined;
|
||||
prev_stream: string | undefined;
|
||||
prev_stream_id: number | undefined;
|
||||
new_stream: string | undefined;
|
||||
};
|
||||
|
||||
const server_message_history_schema = z.object({
|
||||
|
|
|
@ -7,8 +7,8 @@ import type {UserStatusEmojiInfo} from "./user_status";
|
|||
const stored_messages = new Map<number, Message>();
|
||||
|
||||
export type MatchedMessage = {
|
||||
match_content?: string;
|
||||
match_subject?: string;
|
||||
match_content?: string | undefined;
|
||||
match_subject?: string | undefined;
|
||||
};
|
||||
|
||||
export type MessageReactionType = "unicode_emoji" | "realm_emoji" | "zulip_extra_emoji";
|
||||
|
@ -130,7 +130,7 @@ export type Message = (
|
|||
flags?: string[];
|
||||
|
||||
small_avatar_url?: string; // Used in `message_avatar.hbs`
|
||||
status_emoji_info?: UserStatusEmojiInfo; // Used in `message_body.hbs`
|
||||
status_emoji_info?: UserStatusEmojiInfo | undefined; // Used in `message_body.hbs`
|
||||
} & (
|
||||
| {
|
||||
type: "private";
|
||||
|
|
|
@ -10,9 +10,9 @@ type Hook = () => void;
|
|||
export type ModalConfig = {
|
||||
autoremove?: boolean;
|
||||
on_show?: () => void;
|
||||
on_shown?: () => void;
|
||||
on_hide?: () => void;
|
||||
on_hidden?: () => void;
|
||||
on_shown?: (() => void) | undefined;
|
||||
on_hide?: (() => void) | undefined;
|
||||
on_hidden?: (() => void) | undefined;
|
||||
};
|
||||
|
||||
const pre_open_hooks: Hook[] = [];
|
||||
|
|
|
@ -101,8 +101,9 @@ export function set_compose_defaults(): {
|
|||
}
|
||||
}
|
||||
|
||||
if (single.has("topic")) {
|
||||
opts.topic = single.get("topic");
|
||||
const topic = single.get("topic");
|
||||
if (topic !== undefined) {
|
||||
opts.topic = topic;
|
||||
}
|
||||
|
||||
const private_message_recipient = single.get("dm");
|
||||
|
|
|
@ -20,7 +20,7 @@ import * as util from "./util";
|
|||
|
||||
export type ProfileData = {
|
||||
value: string;
|
||||
rendered_value?: string;
|
||||
rendered_value?: string | undefined;
|
||||
};
|
||||
|
||||
export type User = {
|
||||
|
@ -29,7 +29,7 @@ export type User = {
|
|||
email: string;
|
||||
full_name: string;
|
||||
// used for caching result of remove_diacritics.
|
||||
name_with_diacritics_removed?: string;
|
||||
name_with_diacritics_removed?: string | undefined;
|
||||
date_joined: string;
|
||||
is_active: boolean;
|
||||
is_owner: boolean;
|
||||
|
@ -1489,7 +1489,6 @@ export function make_user(user_id: number, email: string, full_name: string): Us
|
|||
// We explicitly don't set `avatar_url` for fake person objects so that fallback code
|
||||
// will ask the server or compute a gravatar URL only once we need the avatar URL,
|
||||
// it's important for performance that we not hash every user's email to get gravatar URLs.
|
||||
avatar_url: undefined,
|
||||
avatar_version: 0,
|
||||
timezone: "",
|
||||
date_joined: "",
|
||||
|
|
|
@ -38,8 +38,8 @@ type DisplayObject = {
|
|||
is_zero: boolean;
|
||||
is_active: boolean;
|
||||
url: string;
|
||||
status_emoji_info?: UserStatusEmojiInfo;
|
||||
user_circle_class?: string;
|
||||
status_emoji_info: UserStatusEmojiInfo | undefined;
|
||||
user_circle_class: string | undefined;
|
||||
is_group: boolean;
|
||||
is_bot: boolean;
|
||||
};
|
||||
|
|
|
@ -19,8 +19,8 @@ import * as people from "./people";
|
|||
export type Event = {sender_id: number; data: InboundData};
|
||||
|
||||
export type PollWidgetExtraData = {
|
||||
question?: string;
|
||||
options?: string[];
|
||||
question?: string | undefined;
|
||||
options?: string[] | undefined;
|
||||
};
|
||||
|
||||
export function activate({
|
||||
|
|
|
@ -4,13 +4,13 @@ import {user_settings} from "./user_settings";
|
|||
|
||||
export type RawPresence = {
|
||||
server_timestamp: number;
|
||||
active_timestamp?: number;
|
||||
idle_timestamp?: number;
|
||||
active_timestamp?: number | undefined;
|
||||
idle_timestamp?: number | undefined;
|
||||
};
|
||||
|
||||
export type PresenceStatus = {
|
||||
status: "active" | "idle" | "offline";
|
||||
last_active?: number;
|
||||
last_active?: number | undefined;
|
||||
};
|
||||
|
||||
export type PresenceInfoFromEvent = {
|
||||
|
|
|
@ -39,7 +39,7 @@ export const invite_schema = z.intersection(
|
|||
]),
|
||||
);
|
||||
type Invite = z.output<typeof invite_schema> & {
|
||||
invited_as_text?: string;
|
||||
invited_as_text?: string | undefined;
|
||||
invited_absolute_time?: string;
|
||||
expiry_date_absolute_time?: string;
|
||||
is_admin?: boolean;
|
||||
|
|
|
@ -704,10 +704,10 @@ function populate_messages_sent_by_client(raw_data: unknown): void {
|
|||
|
||||
const layout: Partial<Plotly.Layout> = {
|
||||
width: 750,
|
||||
height: undefined, // set in draw_plot()
|
||||
// height set in draw_plot()
|
||||
margin: {l: 10, r: 10, b: 40, t: 10},
|
||||
font: font_14pt,
|
||||
xaxis: {range: undefined}, // set in draw_plot()
|
||||
// xaxis set in draw_plot()
|
||||
yaxis: {showticklabels: false},
|
||||
showlegend: false,
|
||||
};
|
||||
|
@ -813,7 +813,7 @@ function populate_messages_sent_by_client(raw_data: unknown): void {
|
|||
$("#id_messages_sent_by_client > div").removeClass("spinner");
|
||||
const data_ = plot_data[user_button][time_button];
|
||||
layout.height = layout.margin!.b! + data_.trace.x.length * 30;
|
||||
layout.xaxis!.range = [0, Math.max(...data_.trace.x) * 1.3];
|
||||
layout.xaxis = {range: [0, Math.max(...data_.trace.x) * 1.3]};
|
||||
void Plotly.newPlot(
|
||||
"id_messages_sent_by_client",
|
||||
[data_.trace, data_.trace_annotations],
|
||||
|
|
|
@ -664,11 +664,11 @@ export function refresh_muted_or_unmuted_stream(sub: StreamSubscription): void {
|
|||
}
|
||||
|
||||
export function get_sidebar_stream_topic_info(filter: Filter): {
|
||||
stream_id?: number;
|
||||
stream_id: number | undefined;
|
||||
topic_selected: boolean;
|
||||
} {
|
||||
const result: {
|
||||
stream_id?: number;
|
||||
stream_id: number | undefined;
|
||||
topic_selected: boolean;
|
||||
} = {
|
||||
stream_id: undefined,
|
||||
|
|
|
@ -141,7 +141,7 @@ export function spinner_li(): ListInfoNode {
|
|||
}
|
||||
|
||||
export class TopicListWidget {
|
||||
prior_dom?: vdom.Tag<ListInfoNodeOptions> = undefined;
|
||||
prior_dom: vdom.Tag<ListInfoNodeOptions> | undefined = undefined;
|
||||
$parent_elem: JQuery;
|
||||
my_stream_id: number;
|
||||
|
||||
|
|
|
@ -97,12 +97,12 @@ type StreamData = {
|
|||
};
|
||||
|
||||
export function render_typeahead_item(args: {
|
||||
primary?: string;
|
||||
primary?: string | undefined;
|
||||
is_person?: boolean;
|
||||
img_src?: string;
|
||||
status_emoji_info?: UserStatusEmojiInfo;
|
||||
status_emoji_info?: UserStatusEmojiInfo | undefined;
|
||||
secondary?: string | null;
|
||||
pronouns?: string;
|
||||
pronouns?: string | undefined;
|
||||
is_user_group?: boolean;
|
||||
stream?: StreamData;
|
||||
is_unsubscribed?: boolean;
|
||||
|
@ -443,10 +443,10 @@ export function sort_recipients<UserType extends UserOrMentionPillData | UserPil
|
|||
}: {
|
||||
users: UserType[];
|
||||
query: string;
|
||||
current_stream_id?: number;
|
||||
current_topic?: string;
|
||||
current_stream_id?: number | undefined;
|
||||
current_topic?: string | undefined;
|
||||
groups?: UserGroupPillData[];
|
||||
max_num_items?: number;
|
||||
max_num_items?: number | undefined;
|
||||
}): (UserType | UserGroupPillData)[] {
|
||||
function sort_relevance(items: UserType[]): UserType[] {
|
||||
return sort_people_for_relevance(items, current_stream_id, current_topic);
|
||||
|
|
|
@ -74,7 +74,7 @@ export function extract_pm_recipients(recipients: string): string[] {
|
|||
// When the type is "private", properties from to_user_ids might be undefined.
|
||||
// See https://github.com/zulip/zulip/pull/23032#discussion_r1038480596.
|
||||
export type Recipient =
|
||||
| {type: "private"; to_user_ids?: string; reply_to: string}
|
||||
| {type: "private"; to_user_ids?: string | undefined; reply_to: string}
|
||||
| ({type: "stream"} & StreamTopic);
|
||||
|
||||
export const same_recipient = function util_same_recipient(a?: Recipient, b?: Recipient): boolean {
|
||||
|
|
|
@ -14,8 +14,8 @@ type ZFormExtraData = {
|
|||
|
||||
// TODO: This TodoWidgetExtraData type should be moved to web/src/todo_widget.js when it will be migrated
|
||||
type TodoWidgetExtraData = {
|
||||
task_list_title?: string;
|
||||
tasks?: {task: string; desc: string}[];
|
||||
task_list_title?: string | undefined;
|
||||
tasks?: {task: string; desc: string}[] | undefined;
|
||||
};
|
||||
|
||||
type WidgetExtraData = PollWidgetExtraData | TodoWidgetExtraData | ZFormExtraData | null;
|
||||
|
|
Loading…
Reference in New Issue