mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
refactor(localize): replace any with unknown in messages and translations utils
Replace unsafe `any` type annotations with `unknown` across the localize
utility layer to improve type safety and catch potential type errors at
compile time rather than at runtime.
Changes in `messages.ts`:
- `ParsedMessage.substitutions`: `Record<string, any>` → `Record<string, unknown>`
- `parseMessage` parameter `expressions`: `readonly any[]` → `readonly unknown[]`
- Local `substitutions` variable: `{[key: string]: any}` → `Record<string, unknown>`
Changes in `translations.ts`:
- `isMissingTranslationError` parameter: `any` → `unknown`, with proper
narrowing (`typeof e === 'object' && e !== null`) before property access
- `MissingTranslationError.type` visibility: `private` → `readonly` to allow
access through the narrowed `unknown` type in the type guard
- `translate` parameter and return type: `readonly any[]` → `readonly unknown[]`
- `makeTemplateObject` cast: `cooked as any` → `cooked as unknown as TemplateStringsArray`
Fix in `mock_message.ts` (test helper):
- `substitutions: []` → `substitutions: {}` — the array literal was only
assignable because the field was typed as `any`; the correct empty value
for a `Record<string, unknown>` is an object literal
This commit is contained in:
committed by
Jessica Janiuk
parent
38d093232c
commit
b10021c79b
@@ -138,7 +138,7 @@ export interface ParsedMessage extends MessageMetadata {
|
||||
/**
|
||||
* A mapping of placeholder names to substitution values.
|
||||
*/
|
||||
substitutions: Record<string, any>;
|
||||
substitutions: Record<string, unknown>;
|
||||
/**
|
||||
* An optional mapping of placeholder names to associated MessageIds.
|
||||
* This can be used to match ICU placeholders to the message that contains the ICU.
|
||||
@@ -170,12 +170,12 @@ export interface ParsedMessage extends MessageMetadata {
|
||||
*/
|
||||
export function parseMessage(
|
||||
messageParts: TemplateStringsArray,
|
||||
expressions?: readonly any[],
|
||||
expressions?: readonly unknown[],
|
||||
location?: SourceLocation,
|
||||
messagePartLocations?: (SourceLocation | undefined)[],
|
||||
expressionLocations: (SourceLocation | undefined)[] = [],
|
||||
): ParsedMessage {
|
||||
const substitutions: {[placeholderName: string]: any} = {};
|
||||
const substitutions: Record<string, unknown> = {};
|
||||
const substitutionLocations: {[placeholderName: string]: SourceLocation | undefined} = {};
|
||||
const associatedMessageIds: {[placeholderName: string]: MessageId} = {};
|
||||
const metadata = parseMetadata(messageParts[0], messageParts.raw[0]);
|
||||
|
||||
@@ -22,14 +22,18 @@ export interface ParsedTranslation extends MessageMetadata {
|
||||
export type ParsedTranslations = Record<MessageId, ParsedTranslation>;
|
||||
|
||||
export class MissingTranslationError extends Error {
|
||||
private readonly type = 'MissingTranslationError';
|
||||
readonly type = 'MissingTranslationError';
|
||||
constructor(readonly parsedMessage: ParsedMessage) {
|
||||
super(`No translation found for ${describeMessage(parsedMessage)}.`);
|
||||
}
|
||||
}
|
||||
|
||||
export function isMissingTranslationError(e: any): e is MissingTranslationError {
|
||||
return e.type === 'MissingTranslationError';
|
||||
export function isMissingTranslationError(e: unknown): e is MissingTranslationError {
|
||||
return (
|
||||
typeof e === 'object' &&
|
||||
e !== null &&
|
||||
(e as MissingTranslationError).type === 'MissingTranslationError'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -51,8 +55,8 @@ export function isMissingTranslationError(e: any): e is MissingTranslationError
|
||||
export function translate(
|
||||
translations: Record<string, ParsedTranslation>,
|
||||
messageParts: TemplateStringsArray,
|
||||
substitutions: readonly any[],
|
||||
): [TemplateStringsArray, readonly any[]] {
|
||||
substitutions: readonly unknown[],
|
||||
): [TemplateStringsArray, readonly unknown[]] {
|
||||
const message = parseMessage(messageParts, substitutions);
|
||||
// Look up the translation using the messageId, and then the legacyId if available.
|
||||
let translation = translations[message.id];
|
||||
@@ -137,7 +141,7 @@ export function makeParsedTranslation(
|
||||
*/
|
||||
export function makeTemplateObject(cooked: string[], raw: string[]): TemplateStringsArray {
|
||||
Object.defineProperty(cooked, 'raw', {value: raw});
|
||||
return cooked as any;
|
||||
return cooked as unknown as TemplateStringsArray;
|
||||
}
|
||||
|
||||
function describeMessage(message: ParsedMessage): string {
|
||||
|
||||
@@ -35,7 +35,7 @@ export function mockMessage(
|
||||
text += `{$${placeholderNames[i - 1]}}${messageParts[i]}`;
|
||||
}
|
||||
return {
|
||||
substitutions: [],
|
||||
substitutions: {},
|
||||
...options,
|
||||
id: options.customId || id, // customId trumps id
|
||||
text,
|
||||
|
||||
Reference in New Issue
Block a user