Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ref(tsc) fix nouncheckedindexedaccess #82791

Merged
merged 18 commits into from
Jan 2, 2025
  •  
  •  
  •  
4 changes: 2 additions & 2 deletions build-utils/sentry-instrumentation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class SentryInstrumentation {
sentry.setTag('arch', os.arch());
sentry.setTag(
'cpu',
cpus?.length ? `${cpus[0].model} (cores: ${cpus.length})}` : 'N/A'
cpus?.length ? `${cpus[0]!.model} (cores: ${cpus.length})}` : 'N/A'
);

this.Sentry = sentry;
Expand All @@ -96,7 +96,7 @@ class SentryInstrumentation {
.filter(assetName => !assetName.endsWith('.map'))
.forEach(assetName => {
const asset = compilation.assets[assetName];
const size = asset.size();
const size = asset!.size();
const file = assetName;
const body = JSON.stringify({
file,
Expand Down
1 change: 1 addition & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -779,6 +779,7 @@ export default typescript.config([
// corresponding configuration object where the plugin is initially included
plugins: {
...react.configs.flat.plugins,
// @ts-ignore noUncheckedIndexedAccess
...react.configs.flat['jsx-runtime'].plugins,
'@typescript-eslint': typescript.plugin,
'react-hooks': fixupPluginRules(reactHooks),
Expand Down
14 changes: 7 additions & 7 deletions static/app/actionCreators/dashboards.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export function fetchDashboards(api: Client, orgSlug: string) {

if (errorResponse) {
const errors = flattenErrors(errorResponse, {});
addErrorMessage(errors[Object.keys(errors)[0]] as string);
addErrorMessage(errors[Object.keys(errors)[0]!] as string);
} else {
addErrorMessage(t('Unable to fetch dashboards'));
}
Expand Down Expand Up @@ -73,7 +73,7 @@ export function createDashboard(

if (errorResponse) {
const errors = flattenErrors(errorResponse, {});
addErrorMessage(errors[Object.keys(errors)[0]] as string);
addErrorMessage(errors[Object.keys(errors)[0]!] as string);
} else {
addErrorMessage(t('Unable to create dashboard'));
}
Expand Down Expand Up @@ -118,7 +118,7 @@ export async function updateDashboardFavorite(
const errorResponse = response?.responseJSON ?? null;
if (errorResponse) {
const errors = flattenErrors(errorResponse, {});
addErrorMessage(errors[Object.keys(errors)[0]] as string);
addErrorMessage(errors[Object.keys(errors)[0]!]! as string);
} else if (isFavorited) {
addErrorMessage(t('Unable to favorite dashboard'));
} else {
Expand All @@ -145,7 +145,7 @@ export function fetchDashboard(

if (errorResponse) {
const errors = flattenErrors(errorResponse, {});
addErrorMessage(errors[Object.keys(errors)[0]] as string);
addErrorMessage(errors[Object.keys(errors)[0]!] as string);
} else {
addErrorMessage(t('Unable to load dashboard'));
}
Expand Down Expand Up @@ -192,7 +192,7 @@ export function updateDashboard(

if (errorResponse) {
const errors = flattenErrors(errorResponse, {});
addErrorMessage(errors[Object.keys(errors)[0]] as string);
addErrorMessage(errors[Object.keys(errors)[0]!] as string);
} else {
addErrorMessage(t('Unable to update dashboard'));
}
Expand All @@ -218,7 +218,7 @@ export function deleteDashboard(

if (errorResponse) {
const errors = flattenErrors(errorResponse, {});
addErrorMessage(errors[Object.keys(errors)[0]] as string);
addErrorMessage(errors[Object.keys(errors)[0]!] as string);
} else {
addErrorMessage(t('Unable to delete dashboard'));
}
Expand Down Expand Up @@ -270,7 +270,7 @@ export function updateDashboardPermissions(

if (errorResponse) {
const errors = flattenErrors(errorResponse, {});
addErrorMessage(errors[Object.keys(errors)[0]] as string);
addErrorMessage(errors[Object.keys(errors)[0]!]! as string);
} else {
addErrorMessage(t('Unable to update dashboard permissions'));
}
Expand Down
2 changes: 1 addition & 1 deletion static/app/actionCreators/members.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export function indexMembersByProject(members: Member[]): IndexedMembersByProjec
acc[project] = [];
}
if (member.user) {
acc[project].push(member.user);
acc[project]!.push(member.user);
}
}
return acc;
Expand Down
2 changes: 1 addition & 1 deletion static/app/actionCreators/monitors.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export async function updateMonitor(
// If we are updating a single value in the monitor we can read the
// validation error for that key, otherwise fallback to the default error
const validationError =
updateKeys.length === 1 ? respError.responseJSON?.[updateKeys[0]]?.[0] : undefined;
updateKeys.length === 1 ? respError.responseJSON?.[updateKeys[0]!]?.[0] : undefined;

logException(err);
addErrorMessage(validationError ?? t('Unable to update monitor.'));
Expand Down
2 changes: 1 addition & 1 deletion static/app/actionCreators/organizations.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export function redirectToRemainingOrganization({
}

// Let's be smart and select the best org to redirect to
const firstRemainingOrg = allOrgs[0];
const firstRemainingOrg = allOrgs[0]!;

const route = `/organizations/${firstRemainingOrg.slug}/issues/`;
if (USING_CUSTOMER_DOMAIN) {
Expand Down
2 changes: 1 addition & 1 deletion static/app/actionCreators/pageFilters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ export function initializeUrlState({
if (projects && projects.length > 0) {
// If there is a list of projects from URL params, select first project
// from that list
newProject = typeof projects === 'string' ? [Number(projects)] : [projects[0]];
newProject = typeof projects === 'string' ? [Number(projects)] : [projects[0]!];
} else {
// When we have finished loading the organization into the props, i.e.
// the organization slug is consistent with the URL param--Sentry will
Expand Down
4 changes: 2 additions & 2 deletions static/app/actionCreators/projects.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ describe('Projects ActionCreators', function () {
expect(mock).not.toHaveBeenCalled();

_debouncedLoadStats(api, new Set([...Array(50)].map((_, i) => String(i))), {
projectId: project.id,
projectId: project!.id,
orgId: organization.slug,
});

Expand All @@ -38,7 +38,7 @@ describe('Projects ActionCreators', function () {
expect(mock).not.toHaveBeenCalled();

_debouncedLoadStats(api, new Set(['1', '2', '3']), {
projectId: project.id,
projectId: project!.id,
orgId: organization.slug,
query: {transactionStats: '1'},
});
Expand Down
6 changes: 3 additions & 3 deletions static/app/bootstrap/initializeSdk.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ export function initializeSdk(config: Config) {
images.push({
type: 'sourcemap',
code_file: filename,
debug_id: debugIdMap[filename],
debug_id: debugIdMap[filename]!,
});
});
} catch (e) {
Expand Down Expand Up @@ -310,7 +310,7 @@ function handlePossibleUndefinedResponseBodyErrors(event: Event): void {
const causeErrorIsURBE = causeError?.type === 'UndefinedResponseBodyError';

if (mainErrorIsURBE || causeErrorIsURBE) {
mainError.type = 'UndefinedResponseBodyError';
mainError!.type = 'UndefinedResponseBodyError';
event.tags = {...event.tags, undefinedResponseBody: true};
event.fingerprint = mainErrorIsURBE
? ['UndefinedResponseBodyError as main error']
Expand All @@ -319,7 +319,7 @@ function handlePossibleUndefinedResponseBodyErrors(event: Event): void {
}

export function addEndpointTagToRequestError(event: Event): void {
const errorMessage = event.exception?.values?.[0].value || '';
const errorMessage = event.exception?.values?.[0]!.value || '';

// The capturing group here turns `GET /dogs/are/great 500` into just `GET /dogs/are/great`
const requestErrorRegex = new RegExp('^([A-Za-z]+ (/[^/]+)+/) \\d+$');
Expand Down
2 changes: 1 addition & 1 deletion static/app/chartcuterie/discover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ discoverCharts.push({
const previousPeriod = LineSeries({
name: t('previous %s', data.seriesName),
data: previous.map(([_, countsForTimestamp], i) => [
current[i][0] * 1000,
current[i]![0] * 1000,
countsForTimestamp.reduce((acc, {count}) => acc + count, 0),
]),
lineStyle: {color: theme.gray200, type: 'dotted'},
Expand Down
6 changes: 3 additions & 3 deletions static/app/components/acl/feature.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,12 +141,12 @@ class Feature extends Component<Props> {

const shouldMatchOnlyProject = feature.match(/^projects:(.+)/);
if (shouldMatchOnlyProject) {
return project.includes(shouldMatchOnlyProject[1]);
return project.includes(shouldMatchOnlyProject[1]!);
}

const shouldMatchOnlyOrg = feature.match(/^organizations:(.+)/);
if (shouldMatchOnlyOrg) {
return organization.includes(shouldMatchOnlyOrg[1]);
return organization.includes(shouldMatchOnlyOrg[1]!);
}

// default, check all feature arrays
Expand Down Expand Up @@ -186,7 +186,7 @@ class Feature extends Component<Props> {
const hooks = HookStore.get(hookName);

if (hooks.length > 0) {
customDisabledRender = hooks[0];
customDisabledRender = hooks[0]!;
}
}
const renderProps = {
Expand Down
4 changes: 2 additions & 2 deletions static/app/components/arithmeticInput/parser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export class TokenConverter {

tokenTerm = (maybeFactor: Expression, remainingAdds: Array<Operation>): Expression => {
if (remainingAdds.length > 0) {
remainingAdds[0].lhs = maybeFactor;
remainingAdds[0]!.lhs = maybeFactor;
return flatten(remainingAdds);
}
return maybeFactor;
Expand All @@ -75,7 +75,7 @@ export class TokenConverter {
};

tokenFactor = (primary: Expression, remaining: Array<Operation>): Operation => {
remaining[0].lhs = primary;
remaining[0]!.lhs = primary;
return flatten(remaining);
};

Expand Down
2 changes: 1 addition & 1 deletion static/app/components/assigneeBadge.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export default storyBook('AssigneeBadge', story => {
const [chevron2Toggle, setChevron2Toggle] = useState<'up' | 'down'>('down');

const team: Team = teams.length
? teams[0]
? teams[0]!
: {
id: '1',
slug: 'team-slug',
Expand Down
2 changes: 1 addition & 1 deletion static/app/components/assigneeSelectorDropdown.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,7 @@ describe('AssigneeSelectorDropdown', () => {

// Suggested assignee initials
expect(options[0]).toHaveTextContent('AB');
await userEvent.click(options[0]);
await userEvent.click(options[0]!);

await waitFor(() =>
expect(assignGroup2Mock).toHaveBeenCalledWith(
Expand Down
17 changes: 8 additions & 9 deletions static/app/components/assigneeSelectorDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ export function AssigneeAvatar({
}

if (suggestedActors.length > 0) {
const actor = suggestedActors[0]!;
return (
<SuggestedAvatarStack
size={26}
Expand All @@ -164,17 +165,12 @@ export function AssigneeAvatar({
<TooltipWrapper>
<div>
{tct('Suggestion: [name]', {
name:
suggestedActors[0].type === 'team'
? `#${suggestedActors[0].name}`
: suggestedActors[0].name,
name: actor.type === 'team' ? `#${actor.name}` : actor.name,
})}
{suggestedActors.length > 1 &&
tn(' + %s other', ' + %s others', suggestedActors.length - 1)}
</div>
<TooltipSubtext>
{suggestedReasons[suggestedActors[0].suggestedReason]}
</TooltipSubtext>
<TooltipSubtext>{suggestedReasons[actor.suggestedReason]}</TooltipSubtext>
</TooltipWrapper>
}
/>
Expand Down Expand Up @@ -265,7 +261,10 @@ export default function AssigneeSelectorDropdown({
const uniqueSuggestions = uniqBy(suggestedOwners, owner => owner.owner);
return uniqueSuggestions
.map<SuggestedAssignee | null>(suggestion => {
const [suggestionType, suggestionId] = suggestion.owner.split(':');
const [suggestionType, suggestionId] = suggestion.owner.split(':') as [
string,
string,
];
const suggestedReasonText = suggestedReasonTable[suggestion.type];
if (suggestionType === 'user') {
const member = currentMemberList.find(user => user.id === suggestionId);
Expand Down Expand Up @@ -322,7 +321,7 @@ export default function AssigneeSelectorDropdown({
}
// See makeMemberOption and makeTeamOption for how the value is formatted
const type = selectedOption.value.startsWith('user:') ? 'user' : 'team';
const assigneeId = selectedOption.value.split(':')[1];
const assigneeId = selectedOption.value.split(':')[1]!;
let assignee: User | Actor;

if (type === 'user') {
Expand Down
2 changes: 1 addition & 1 deletion static/app/components/assistant/guideAnchor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ class BaseGuideAnchor extends Component<Props, State> {

const totalStepCount = currentGuide.steps.length;
const currentStepCount = step + 1;
const currentStep = currentGuide.steps[step];
const currentStep = currentGuide.steps[step]!;
const lastStep = currentStepCount === totalStepCount;
const hasManySteps = totalStepCount > 1;

Expand Down
4 changes: 2 additions & 2 deletions static/app/components/autoComplete.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ describe('AutoComplete', function () {
expect(screen.getByTestId('test-autocomplete')).toBeInTheDocument();
expect(screen.getAllByRole('option')).toHaveLength(3);

fireEvent.click(screen.getByText(items[1].name));
fireEvent.click(screen.getByText(items[1]!.name));
expect(mocks.onSelect).toHaveBeenCalledWith(
items[1],
expect.objectContaining({inputValue: '', highlightedIndex: 0}),
Expand Down Expand Up @@ -419,7 +419,7 @@ describe('AutoComplete', function () {
createWrapper({isOpen: true});
expect(screen.getAllByRole('option')).toHaveLength(3);

fireEvent.click(screen.getByText(items[1].name));
fireEvent.click(screen.getByText(items[1]!.name));
expect(mocks.onSelect).toHaveBeenCalledWith(
items[1],
expect.objectContaining({inputValue: '', highlightedIndex: 0}),
Expand Down
24 changes: 12 additions & 12 deletions static/app/components/avatar/avatarList.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@ describe('AvatarList', () => {
];

renderComponent({users});
expect(screen.getByText(users[0].name.charAt(0))).toBeInTheDocument();
expect(screen.getByText(users[1].name.charAt(0))).toBeInTheDocument();
expect(screen.getByText(users[2].name.charAt(0))).toBeInTheDocument();
expect(screen.getByText(users[3].name.charAt(0))).toBeInTheDocument();
expect(screen.getByText(users[4].name.charAt(0))).toBeInTheDocument();
expect(screen.getByText(users[5].name.charAt(0))).toBeInTheDocument();
expect(screen.getByText(users[0]!.name.charAt(0))).toBeInTheDocument();
expect(screen.getByText(users[1]!.name.charAt(0))).toBeInTheDocument();
expect(screen.getByText(users[2]!.name.charAt(0))).toBeInTheDocument();
expect(screen.getByText(users[3]!.name.charAt(0))).toBeInTheDocument();
expect(screen.getByText(users[4]!.name.charAt(0))).toBeInTheDocument();
expect(screen.getByText(users[5]!.name.charAt(0))).toBeInTheDocument();
expect(screen.queryByTestId('avatarList-collapsedavatars')).not.toBeInTheDocument();
});

Expand All @@ -63,12 +63,12 @@ describe('AvatarList', () => {
];

renderComponent({users});
expect(screen.getByText(users[0].name.charAt(0))).toBeInTheDocument();
expect(screen.getByText(users[1].name.charAt(0))).toBeInTheDocument();
expect(screen.getByText(users[2].name.charAt(0))).toBeInTheDocument();
expect(screen.getByText(users[3].name.charAt(0))).toBeInTheDocument();
expect(screen.getByText(users[4].name.charAt(0))).toBeInTheDocument();
expect(screen.queryByText(users[5].name.charAt(0))).not.toBeInTheDocument();
expect(screen.getByText(users[0]!.name.charAt(0))).toBeInTheDocument();
expect(screen.getByText(users[1]!.name.charAt(0))).toBeInTheDocument();
expect(screen.getByText(users[2]!.name.charAt(0))).toBeInTheDocument();
expect(screen.getByText(users[3]!.name.charAt(0))).toBeInTheDocument();
expect(screen.getByText(users[4]!.name.charAt(0))).toBeInTheDocument();
expect(screen.queryByText(users[5]!.name.charAt(0))).not.toBeInTheDocument();
expect(screen.getByTestId('avatarList-collapsedavatars')).toBeInTheDocument();
});

Expand Down
4 changes: 2 additions & 2 deletions static/app/components/avatar/avatarList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@ function AvatarList({

if (numCollapsedAvatars === 1) {
if (visibleTeamAvatars.length < teams.length) {
visibleTeamAvatars.unshift(teams[teams.length - 1]);
visibleTeamAvatars.unshift(teams[teams.length - 1]!);
} else if (visibleUserAvatars.length < users.length) {
visibleUserAvatars.unshift(users[users.length - 1]);
visibleUserAvatars.unshift(users[users.length - 1]!);
}
numCollapsedAvatars = 0;
}
Expand Down
2 changes: 1 addition & 1 deletion static/app/components/avatar/index.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ describe('Avatar', function () {
avatar2.unmount();

// avatarType of `default`
sentryApp.avatars![0].avatarType = 'default';
sentryApp.avatars![0]!.avatarType = 'default';
render(<AvatarComponent sentryApp={sentryApp} isColor />);
expect(screen.getByTestId('default-sentry-app-avatar')).toBeInTheDocument();
});
Expand Down
4 changes: 2 additions & 2 deletions static/app/components/avatar/suggestedAvatarStack.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ function SuggestedAvatarStack({
<AvatarStack reverse={reverse} data-test-id="suggested-avatar-stack">
{suggestedOwners.slice(0, numAvatars - 1).map((owner, i) => (
<Avatar
round={firstSuggestion.type === 'user'}
round={firstSuggestion!.type === 'user'}
actor={owner}
hasTooltip={false}
{...props}
Expand All @@ -40,7 +40,7 @@ function SuggestedAvatarStack({
/>
))}
<Avatar
actor={firstSuggestion}
actor={firstSuggestion!}
tooltip={tooltip}
tooltipOptions={{...tooltipOptions, skipWrapper: true}}
{...props}
Expand Down
Loading
Loading