Disallow unsafe type assertions (#18688)

This commit is contained in:
Christian Gunderman
2026-02-10 00:10:15 +00:00
committed by GitHub
parent bce1caefd0
commit fd65416a2f
188 changed files with 592 additions and 47 deletions

View File

@@ -123,6 +123,7 @@ function getNestedValue(
for (const key of path) {
if (current === null || current === undefined) return undefined;
if (typeof current !== 'object') return undefined;
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
current = (current as Record<string, unknown>)[key];
}
return current;
@@ -144,8 +145,10 @@ function setNestedValue(
if (current[key] === undefined || current[key] === null) {
current[key] = {};
} else {
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
current[key] = { ...(current[key] as Record<string, unknown>) };
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
current = current[key] as Record<string, unknown>;
}
@@ -265,6 +268,7 @@ export function AgentConfigDialog({
() =>
AGENT_CONFIG_FIELDS.map((field) => {
const currentValue = getNestedValue(
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
pendingOverride as Record<string, unknown>,
field.path,
);
@@ -300,6 +304,7 @@ export function AgentConfigDialog({
displayValue,
isGreyedOut: currentValue === undefined,
scopeMessage: undefined,
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
rawValue: rawValue as string | number | boolean | undefined,
};
}),
@@ -320,6 +325,7 @@ export function AgentConfigDialog({
if (!field || field.type !== 'boolean') return;
const currentValue = getNestedValue(
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
pendingOverride as Record<string, unknown>,
field.path,
);
@@ -329,6 +335,7 @@ export function AgentConfigDialog({
const newValue = !effectiveValue;
const newOverride = setNestedValue(
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
pendingOverride as Record<string, unknown>,
field.path,
newValue,
@@ -369,6 +376,7 @@ export function AgentConfigDialog({
// Update pending override locally
const newOverride = setNestedValue(
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
pendingOverride as Record<string, unknown>,
field.path,
parsed,
@@ -391,6 +399,7 @@ export function AgentConfigDialog({
// Remove the override (set to undefined)
const newOverride = setNestedValue(
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
pendingOverride as Record<string, unknown>,
field.path,
undefined,

View File

@@ -132,6 +132,7 @@ export function EditorSettingsDialog({
) {
mergedEditorName =
EDITOR_DISPLAY_NAMES[
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
settings.merged.general.preferredEditor as EditorType
];
}

View File

@@ -133,6 +133,7 @@ export const MultiFolderTrustDialog: React.FC<MultiFolderTrustDialogProps> = ({
workspaceContext.addDirectory(expandedPath);
added.push(dir);
} catch (e) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
const error = e as Error;
errors.push(`Error adding '${dir}': ${error.message}`);
}

View File

@@ -259,10 +259,12 @@ export function SettingsDialog({
key,
label: definition?.label || key,
description: definition?.description,
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
type: type as 'boolean' | 'number' | 'string' | 'enum',
displayValue,
isGreyedOut,
scopeMessage,
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
rawValue: rawValue as string | number | boolean | undefined,
};
});
@@ -283,8 +285,10 @@ export function SettingsDialog({
const currentValue = getEffectiveValue(key, pendingSettings, {});
let newValue: SettingsValue;
if (definition?.type === 'boolean') {
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
newValue = !(currentValue as boolean);
setPendingSettings((prev) =>
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
setPendingSettingValue(key, newValue as boolean, prev),
);
} else if (definition?.type === 'enum' && definition.options) {
@@ -377,6 +381,7 @@ export function SettingsDialog({
// Record pending change globally
setGlobalPendingChanges((prev) => {
const next = new Map(prev);
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
next.set(key, newValue as PendingValue);
return next;
});

View File

@@ -75,6 +75,7 @@ export function Table<T>({ data, columns }: TableProps<T>) {
col.renderCell(item)
) : (
<Text color={theme.text.primary}>
{/* eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion */}
{String((item as Record<string, unknown>)[col.key])}
</Text>
)}

View File

@@ -121,6 +121,7 @@ export const ToolResultDisplay: React.FC<ToolResultDisplayProps> = ({
// where Container grows -> List renders more -> Container grows.
const limit = maxLines ?? availableHeight ?? ACTIVE_SHELL_MAX_LINES;
const listHeight = Math.min(
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
(truncatedResultDisplay as AnsiOutput).length,
limit,
);
@@ -129,6 +130,7 @@ export const ToolResultDisplay: React.FC<ToolResultDisplayProps> = ({
<Box width={childWidth} flexDirection="column" maxHeight={listHeight}>
<ScrollableList
width={childWidth}
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
data={truncatedResultDisplay as AnsiOutput}
renderItem={renderVirtualizedAnsiLine}
estimatedItemHeight={() => 1}
@@ -184,7 +186,9 @@ export const ToolResultDisplay: React.FC<ToolResultDisplayProps> = ({
) {
content = (
<DiffRenderer
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
diffContent={(truncatedResultDisplay as FileDiffResult).fileDiff}
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
filename={(truncatedResultDisplay as FileDiffResult).fileName}
availableTerminalHeight={availableHeight}
terminalWidth={childWidth}
@@ -197,6 +201,7 @@ export const ToolResultDisplay: React.FC<ToolResultDisplayProps> = ({
content = (
<AnsiOutputText
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
data={truncatedResultDisplay as AnsiOutput}
availableTerminalHeight={
isAlternateBuffer ? undefined : availableHeight

View File

@@ -153,6 +153,7 @@ export const Scrollable: React.FC<ScrollableProps> = ({
const scrollableEntry = useMemo(
() => ({
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
ref: ref as React.RefObject<DOMElement>,
getScrollState,
scrollBy: scrollByWithAnimation,

View File

@@ -219,6 +219,7 @@ function ScrollableList<T>(
const scrollableEntry = useMemo(
() => ({
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
ref: containerRef as React.RefObject<DOMElement>,
getScrollState,
scrollBy: scrollByWithAnimation,
@@ -254,6 +255,7 @@ function ScrollableList<T>(
);
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
const ScrollableListWithForwardRef = forwardRef(ScrollableList) as <T>(
props: ScrollableListProps<T> & { ref?: React.Ref<ScrollableListRef<T>> },
) => React.ReactElement;

View File

@@ -492,6 +492,7 @@ function VirtualizedList<T>(
);
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
const VirtualizedListWithForwardRef = forwardRef(VirtualizedList) as <T>(
props: VirtualizedListProps<T> & { ref?: React.Ref<VirtualizedListRef<T>> },
) => React.ReactElement;

View File

@@ -157,6 +157,7 @@ export const TriageDuplicates = ({
'--json',
'number,title,body,state,stateReason,labels,url,comments,author,reactionGroups',
]);
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
return JSON.parse(stdout) as Candidate;
} catch (err) {
debugLogger.error(
@@ -280,6 +281,7 @@ Return a JSON object with:
promptId: 'triage-duplicates',
});
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
const rec = response as unknown as GeminiRecommendation;
let canonical: Candidate | undefined;

View File

@@ -225,6 +225,7 @@ Return a JSON object with:
promptId: 'triage-issues',
});
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
return response as unknown as AnalysisResult;
},
[config],