Thursday, July 21, 2022

Sizes of Windows integral types

While developing WinSafe, it’s very common to convert the Windows integral data types to their Rust equivalent. Care must be taken, however, when it comes to pointer size, which varies according to the architecture. Since WinSafe is aimed to both 32 and 64-bit Windows, I must pay attention.

For reference, below is the table I’m using to figure out the sizes:

Signed C Signed Rust Unsigned C Unsigned Rust 32-bit 64-bit
CHAR
 
 
i8 UCHAR
BYTE
BOOLEAN
u8 8 bit (1 byte)
SHORT
 
 
i16 USHORT
WCHAR
WORD
u16 16 bit (2 byte)
BOOL
INT
LONG
 
i32  
UINT
ULONG
DWORD
u32 32 bit (4 byte)
INT_PTR
LONG_PTR
LPARAM
 
isize UINT_PTR
ULONG_PTR
WPARAM
SIZE_T
usize 32 bit (4 byte) 64 bit (8 byte)
LARGE_INTEGER
LONG64
LONGLONG
 
 
i64 ULARGE_INTEGER
ULONG64
ULONGLONG
DWORD64
DWORDLONG
QWORD
u64 64 bit (8 byte)

The table above is an extension of this one.

Tuesday, July 19, 2022

Default props in React function components

Having default props in a React component is a rather common situation. The most popular way to accomplish this is to pass the default values to a defaultProps property on the function component. However, this property will be deprecated in the future.

Spoiler: due to the sheer amount of code written with it, it never will be deprecated. It’s more likely that a warning will show in the console.

Anyway, in order to keep things clean and guard from this future warning, I came up with a clean pure TypeScript solution to this problem:

interface Props {
	name: string;
	surname?: string;
	age?: number;
}

const defaultProps = {
	surname: 'Doe',
};

function MyComponent(props0: Props) {
	const props = {...defaultProps, ...props0};

	return <div>{props.surname}</div>;
}

The code above provides the correct behavior and proper TypeScript validation. It ended becoming an answer on StackOverflow.

Since the spread order may be a a bit hard to remember, this function does the trick:

export function defProp<P, D>(props: P, defaultProps: D): P & D {
	return {...defaultProps, ...props};
}

function MyComponent(props0: Props) {
	const props = defProp(props0, defaultProps);

	// ...
}

Thursday, July 7, 2022

Extending built-in TypeScript objects in Vite

Checking whether an array is empty is a rather common operation. The usual way to do this in TypeScript is by checking the length property, but it’s very verbose:

if (myArray.length === 0) {
	// ...
}

For some reason, the JavaScript standard doesn’t specify an isEmpty() method. Fortunately, we can extend native JavaScript objects to add any methods we want. While this is a great feature, I was unable to make it work in a Vue + TypeScript + Vite project. I want the autocomplete of my VSCode to properly display it.

To make the TypeScript compiler recognize it, you must declare your method extensions as global by wrapping the declaration in a declare global block.

At first I tried to write the declaration in the “src/env.d.ts” file, but it didn’t work. Turns out you need to place them in a different file, as explained here. So I finally wrote them in a “src/extensions.d.ts” for the typings, and then the implementations themselves must be in a file that will be actually called in your application:

I tested the code above in a Vue project, but I believe it will work accordingly in a React project as well.