```ts
export function matchSetting(rules: Record<string, string>, name: string): string | null {
  if (typeof name !== "string" || name === "" || name.includes("*") || !/^[a-zA-Z0-9.]*$/.test(name)) {
    throw new Error("name must be a star-free non-empty string");
  }

  let match = null;
  let maxSpecificity = -1;

  for (const selector in rules) {
    if (rules.hasOwnProperty(selector)) {
      const value = rules[selector];
      if (typeof value !== "string") {
        throw new Error("rule values must be strings");
      }
      if (selector === name) {
        return value;
      } else if (selector.endsWith(".*")) {
        const prefix = selector.slice(0, -2);
        if (name.startsWith(prefix)) {
          const specificity = name.length - prefix.length;
          if (specificity > maxSpecificity) {
            match = value;
            maxSpecificity = specificity;
          }
        }
      } else if (selector === "*") {
        match = value;
      }
    }
  }

  return match;
}
```