Disallow underspecified types (#21485)

This commit is contained in:
Christian Gunderman
2026-03-07 21:05:38 +00:00
committed by GitHub
parent 245b68e9f1
commit dac3735626
18 changed files with 51 additions and 7 deletions
+2
View File
@@ -832,7 +832,9 @@ export class Task {
if (
part.kind !== 'data' ||
!part.data ||
// eslint-disable-next-line no-restricted-syntax
typeof part.data['callId'] !== 'string' ||
// eslint-disable-next-line no-restricted-syntax
typeof part.data['outcome'] !== 'string'
) {
return false;
@@ -79,6 +79,7 @@ function migrateClaudeHook(claudeHook: unknown): unknown {
migrated['command'] = hook['command'];
// Replace CLAUDE_PROJECT_DIR with GEMINI_PROJECT_DIR in command
// eslint-disable-next-line no-restricted-syntax
if (typeof migrated['command'] === 'string') {
migrated['command'] = migrated['command'].replace(
/\$CLAUDE_PROJECT_DIR/g,
@@ -93,6 +94,7 @@ function migrateClaudeHook(claudeHook: unknown): unknown {
}
// Map timeout field (Claude uses seconds, Gemini uses seconds)
// eslint-disable-next-line no-restricted-syntax
if ('timeout' in hook && typeof hook['timeout'] === 'number') {
migrated['timeout'] = hook['timeout'];
}
@@ -140,6 +142,7 @@ function migrateClaudeHooks(claudeConfig: unknown): Record<string, unknown> {
// Transform matcher
if (
'matcher' in definition &&
// eslint-disable-next-line no-restricted-syntax
typeof definition['matcher'] === 'string'
) {
migratedDef['matcher'] = transformMatcher(definition['matcher']);
@@ -65,6 +65,7 @@ export function mockCoreDebugLogger<T extends Record<string, unknown>>(
return {
...actual,
coreEvents: {
// eslint-disable-next-line no-restricted-syntax
...(typeof actual['coreEvents'] === 'object' &&
actual['coreEvents'] !== null
? actual['coreEvents']
+1
View File
@@ -96,6 +96,7 @@ function isInkRenderMetrics(
typeof m === 'object' &&
m !== null &&
'output' in m &&
// eslint-disable-next-line no-restricted-syntax
typeof m['output'] === 'string'
);
}
@@ -502,7 +502,9 @@ export const useSlashCommandProcessor = (
const props = result.props as Record<string, unknown>;
if (
!props ||
// eslint-disable-next-line no-restricted-syntax
typeof props['name'] !== 'string' ||
// eslint-disable-next-line no-restricted-syntax
typeof props['displayName'] !== 'string' ||
!props['definition']
) {
+6 -4
View File
@@ -494,9 +494,10 @@ export class ActivityLogger extends EventEmitter {
req.write = function (chunk: string | Uint8Array, ...etc: unknown[]) {
if (chunk) {
const arg0 = etc[0];
const encoding =
typeof etc[0] === 'string' && Buffer.isEncoding(etc[0])
? etc[0]
typeof arg0 === 'string' && Buffer.isEncoding(arg0)
? arg0
: undefined;
requestChunks.push(
Buffer.isBuffer(chunk)
@@ -519,9 +520,10 @@ export class ActivityLogger extends EventEmitter {
) {
const chunk = typeof chunkOrCb === 'function' ? undefined : chunkOrCb;
if (chunk) {
const arg0 = etc[0];
const encoding =
typeof etc[0] === 'string' && Buffer.isEncoding(etc[0])
? etc[0]
typeof arg0 === 'string' && Buffer.isEncoding(arg0)
? arg0
: undefined;
requestChunks.push(
Buffer.isBuffer(chunk)
@@ -119,6 +119,7 @@ export class BrowserAgentInvocation extends BaseToolInvocation<
if (
activity.type === 'THOUGHT_CHUNK' &&
// eslint-disable-next-line no-restricted-syntax
typeof activity.data['text'] === 'string'
) {
updateOutput(`🌐💭 ${activity.data['text']}`);
@@ -356,6 +356,7 @@ class TypeTextDeclarativeTool extends DeclarativeTool<
params: Record<string, unknown>,
): ToolInvocation<Record<string, unknown>, ToolResult> {
const submitKey =
// eslint-disable-next-line no-restricted-syntax
typeof params['submitKey'] === 'string' && params['submitKey']
? params['submitKey']
: undefined;
@@ -355,6 +355,7 @@ export class HookAggregator {
// Extract additionalContext from various hook types
if (
'additionalContext' in specific &&
// eslint-disable-next-line no-restricted-syntax
typeof specific['additionalContext'] === 'string'
) {
contexts.push(specific['additionalContext']);
@@ -132,7 +132,11 @@ export class FolderTrustDiscoveryService {
for (const event of Object.values(hooksConfig)) {
if (!Array.isArray(event)) continue;
for (const hook of event) {
if (this.isRecord(hook) && typeof hook['command'] === 'string') {
if (
this.isRecord(hook) &&
// eslint-disable-next-line no-restricted-syntax
typeof hook['command'] === 'string'
) {
hooks.add(hook['command']);
}
}
@@ -156,11 +156,13 @@ async function truncateHistoryToBudget(
} else if (responseObj && typeof responseObj === 'object') {
if (
'output' in responseObj &&
// eslint-disable-next-line no-restricted-syntax
typeof responseObj['output'] === 'string'
) {
contentStr = responseObj['output'];
} else if (
'content' in responseObj &&
// eslint-disable-next-line no-restricted-syntax
typeof responseObj['content'] === 'string'
) {
contentStr = responseObj['content'];
@@ -579,10 +579,12 @@ export class LoopDetectionService {
}
const flashConfidence =
// eslint-disable-next-line no-restricted-syntax
typeof flashResult['unproductive_state_confidence'] === 'number'
? flashResult['unproductive_state_confidence']
: 0;
const flashAnalysis =
// eslint-disable-next-line no-restricted-syntax
typeof flashResult['unproductive_state_analysis'] === 'string'
? flashResult['unproductive_state_analysis']
: '';
@@ -628,11 +630,13 @@ export class LoopDetectionService {
const mainModelConfidence =
mainModelResult &&
// eslint-disable-next-line no-restricted-syntax
typeof mainModelResult['unproductive_state_confidence'] === 'number'
? mainModelResult['unproductive_state_confidence']
: 0;
const mainModelAnalysis =
mainModelResult &&
// eslint-disable-next-line no-restricted-syntax
typeof mainModelResult['unproductive_state_analysis'] === 'string'
? mainModelResult['unproductive_state_analysis']
: undefined;
@@ -681,6 +685,7 @@ export class LoopDetectionService {
if (
result &&
// eslint-disable-next-line no-restricted-syntax
typeof result['unproductive_state_confidence'] === 'number'
) {
return result;
+2
View File
@@ -63,6 +63,7 @@ function getStringReferences(parts: AnyPart[]): StringReference[] {
});
}
} else if (part instanceof GenericPart) {
// eslint-disable-next-line no-restricted-syntax
if (part.type === 'executableCode' && typeof part['code'] === 'string') {
refs.push({
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
@@ -73,6 +74,7 @@ function getStringReferences(parts: AnyPart[]): StringReference[] {
});
} else if (
part.type === 'codeExecutionResult' &&
// eslint-disable-next-line no-restricted-syntax
typeof part['output'] === 'string'
) {
refs.push({
+1 -1
View File
@@ -107,7 +107,7 @@ export function isMcpToolAnnotation(
return (
typeof annotation === 'object' &&
annotation !== null &&
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion, no-restricted-syntax
typeof (annotation as Record<string, unknown>)['_serverName'] === 'string'
);
}
+1
View File
@@ -112,6 +112,7 @@ Return ONLY the corrected string in the specified JSON format with the key 'corr
if (
result &&
// eslint-disable-next-line no-restricted-syntax
typeof result['corrected_string_escaping'] === 'string' &&
result['corrected_string_escaping'].length > 0
) {
+1
View File
@@ -209,6 +209,7 @@ export function parseGoogleApiError(error: unknown): GoogleApiError | null {
}
// Basic structural check before casting.
// Since the proto definitions are loose, we primarily rely on @type presence.
// eslint-disable-next-line no-restricted-syntax
if (typeof detailObj['@type'] === 'string') {
// We can just cast it; the consumer will have to switch on @type
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
+5
View File
@@ -361,19 +361,24 @@ async function parseTokenEndpointResponse(
data &&
typeof data === 'object' &&
'access_token' in data &&
// eslint-disable-next-line no-restricted-syntax
typeof (data as Record<string, unknown>)['access_token'] === 'string'
) {
const obj = data as Record<string, unknown>;
const result: OAuthTokenResponse = {
access_token: String(obj['access_token']),
token_type:
// eslint-disable-next-line no-restricted-syntax
typeof obj['token_type'] === 'string' ? obj['token_type'] : 'Bearer',
expires_in:
// eslint-disable-next-line no-restricted-syntax
typeof obj['expires_in'] === 'number' ? obj['expires_in'] : undefined,
refresh_token:
// eslint-disable-next-line no-restricted-syntax
typeof obj['refresh_token'] === 'string'
? obj['refresh_token']
: undefined,
// eslint-disable-next-line no-restricted-syntax
scope: typeof obj['scope'] === 'string' ? obj['scope'] : undefined,
};
return result;