Repository: rollup/rollup
File: src/utils/FileEmitter.ts (TypeScript)

Code before:
	fileName: string | undefined;
	name: string | undefined;
	needsCodeReference: boolean;
	referenceId: string;
	source: string | Uint8Array | undefined;
	type: 'asset';
}

interface EmittedFile {
	[key: string]: unknown;
	fileName?: string;
	name?: string;
	type: 'chunk' | 'asset' | 'prebuilt-chunk';
}

type ConsumedFile = ConsumedChunk | ConsumedAsset | ConsumedPrebuiltChunk;

function hasValidType(emittedFile: unknown): emittedFile is {
	[key: string]: unknown;
	type: 'asset' | 'chunk' | 'prebuilt-chunk';
} {
	return Boolean(
		emittedFile &&
			((emittedFile as { [key: string]: unknown }).type === 'asset' ||
				(emittedFile as { [key: string]: unknown }).type === 'chunk' ||
				(emittedFile as { [key: string]: unknown }).type === 'prebuilt-chunk')
	);
}

function hasValidName(emittedFile: {
	[key: string]: unknown;
	type: 'asset' | 'chunk' | 'prebuilt-chunk';
}): emittedFile is EmittedFile {
	const validatedName = emittedFile.fileName || emittedFile.name;
	return !validatedName || (typeof validatedName === 'string' && !isPathFragment(validatedName));
}

function getValidSource(
	source: unknown,
	emittedFile: { fileName?: string; name?: string },
	fileReferenceId: string | null
): string | Uint8Array {
	if (!(typeof source === 'string' || source instanceof Uint8Array)) {
		const assetName = emittedFile.fileName || emittedFile.name || fileReferenceId;
		return error(
			errorFailedValidation(
				`Could not set source for ${
					typeof assetName === 'string' ? `asset "${assetName}"` : 'unnamed asset'
				}, asset source needs to be a string, Uint8Array or Buffer.`
			)
		);

Review comment (suggestion):
To avoid some repetition, maybe

```js
const fileTypes = ['asset' as const, 'chunk' as const, 'prebuilt-chunk' as const];
type FileType = (typeof fileTypes)[number];

function hasValidType(emittedFile: unknown): emittedFile is {
	[key: string]: unknown;
	type: FileType;
} {
	return Boolean(
		emittedFile && fileTypes.includes((emittedFile as { [key: string]: unknown }).type));
}
```

Then you can also use `FileType` anywhere else you would write `'asset' | 'chunk' | 'prebuilt-chunk'`

Code after:
	referenceId: string;
};

type ConsumedFile = ConsumedChunk | ConsumedAsset | ConsumedPrebuiltChunk;

type EmittedFileType = ConsumedFile['type'];

interface EmittedFile {
	[key: string]: unknown;
	fileName?: string;
	name?: string;
	type: EmittedFileType;
}

const emittedFileTypes: Set<EmittedFileType> = new Set(['chunk', 'asset', 'prebuilt-chunk']);

function hasValidType(emittedFile: unknown): emittedFile is {
	[key: string]: unknown;
	type: EmittedFileType;
} {
	return Boolean(
		emittedFile &&
			emittedFileTypes.has((emittedFile as { [key: string]: unknown; type: EmittedFileType }).type)
	);
}

function hasValidName(emittedFile: {
	[key: string]: unknown;
	type: EmittedFileType;
}): emittedFile is EmittedFile {
	const validatedName = emittedFile.fileName || emittedFile.name;
	return !validatedName || (typeof validatedName === 'string' && !isPathFragment(validatedName));
}

function getValidSource(
	source: unknown,
	emittedFile: { fileName?: string; name?: string },
	fileReferenceId: string | null
): string | Uint8Array {
	if (!(typeof source === 'string' || source instanceof Uint8Array)) {
		const assetName = emittedFile.fileName || emittedFile.name || fileReferenceId;
		return error(
			errorFailedValidation(
				`Could not set source for ${
					typeof assetName === 'string' ? `asset "${assetName}"` : 'unnamed asset'
				}, asset source needs to be a string, Uint8Array or Buffer.`
			)
		);
	}
	return source;
}